@birdapi/velinstyle 0.8.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 (313) hide show
  1. package/README.de.md +135 -246
  2. package/README.md +134 -245
  3. package/cli/blueprints/onboarding.html +2 -2
  4. package/cli/cli-manifest.json +97 -0
  5. package/cli/docgen/extract-a11y.js +89 -0
  6. package/cli/docgen/extract-attributes.js +95 -0
  7. package/cli/docgen/extract-cli.js +50 -0
  8. package/cli/docgen/extract-components.js +175 -0
  9. package/cli/docgen/extract-meta.js +32 -0
  10. package/cli/docgen/extract-rules.js +76 -0
  11. package/cli/docgen/extract-tokens.js +79 -0
  12. package/cli/docgen/extract-utilities.js +75 -0
  13. package/cli/docgen/markdown.js +43 -0
  14. package/cli/docs-generate.js +196 -0
  15. package/cli/index.js +121 -5
  16. package/cli/meta.js +97 -0
  17. package/cli/perf-audit.js +174 -0
  18. package/cli/pii-scanner.js +134 -0
  19. package/cli/scanner-rules-data.js +62 -0
  20. package/cli/scanner.js +68 -1
  21. package/cli/search-index.js +163 -0
  22. package/cli/tokens-build.js +21 -1
  23. package/cli/tokens-validate.js +69 -0
  24. package/components/a11y-entry.js +42 -0
  25. package/components/a11y-utils.js +71 -0
  26. package/components/focus-manager.js +45 -8
  27. package/components/index.js +22 -12
  28. package/components/runtime/component-loaders.js +43 -0
  29. package/components/runtime/index.js +77 -0
  30. package/components/runtime-entry.js +10 -0
  31. package/components/sanitize.js +135 -54
  32. package/components/velin-accordion.js +12 -0
  33. package/components/velin-bottom-nav.js +19 -0
  34. package/components/velin-carousel.js +2 -2
  35. package/components/velin-code-block.js +142 -0
  36. package/components/velin-command.js +15 -0
  37. package/components/velin-copy.js +18 -5
  38. package/components/velin-counter.js +3 -0
  39. package/components/velin-dialog.js +9 -1
  40. package/components/velin-email.js +94 -0
  41. package/components/velin-icon.js +65 -22
  42. package/components/velin-lightbox.js +8 -3
  43. package/components/velin-live-dot.js +5 -0
  44. package/components/velin-modal.js +6 -3
  45. package/components/velin-popover.js +34 -2
  46. package/components/velin-reveal.js +7 -65
  47. package/components/velin-scroll-top.js +1 -1
  48. package/components/velin-search.js +267 -0
  49. package/components/velin-secure-field.js +99 -0
  50. package/components/velin-sparkline.js +27 -7
  51. package/components/{velin-stepper-wc.js → velin-stepper.js} +37 -8
  52. package/components/velin-theme-toggle.js +12 -5
  53. package/components/velin-toast.js +4 -0
  54. package/components/{velin-tooltip-wc.js → velin-tooltip.js} +22 -3
  55. package/core/a11y/component-contracts.json +221 -0
  56. package/core/attributes/index.js +6 -0
  57. package/core/attributes/registry.js +268 -0
  58. package/core/highlight/highlight.js +114 -0
  59. package/core/highlight/index.js +29 -0
  60. package/core/highlight/languages/_utils.js +52 -0
  61. package/core/highlight/languages/blade.js +16 -0
  62. package/core/highlight/languages/css.js +26 -0
  63. package/core/highlight/languages/html.js +17 -0
  64. package/core/highlight/languages/js.js +58 -0
  65. package/core/highlight/languages/json.js +14 -0
  66. package/core/highlight/languages/markdown.js +16 -0
  67. package/core/highlight/languages/php.js +39 -0
  68. package/core/highlight/languages/plain.js +7 -0
  69. package/core/highlight/languages/shell.js +33 -0
  70. package/core/highlight/languages/sql.js +20 -0
  71. package/core/highlight/languages/typescript.js +28 -0
  72. package/core/highlight/observe.js +53 -0
  73. package/core/highlight/registry.js +107 -0
  74. package/core/highlight/render.js +35 -0
  75. package/core/highlight/types.js +28 -0
  76. package/core/meta/build.js +293 -0
  77. package/core/meta/index.js +17 -0
  78. package/core/meta/schema.js +49 -0
  79. package/core/motion/effects.js +54 -0
  80. package/core/motion/index.js +76 -0
  81. package/core/motion/scheduler.js +72 -0
  82. package/core/motion/scroll.js +32 -0
  83. package/core/motion/stagger.js +24 -0
  84. package/core/search/docs-url.js +96 -0
  85. package/core/search/engine.js +139 -0
  86. package/core/search/highlight.js +48 -0
  87. package/core/search/index.js +126 -0
  88. package/core/search/providers.js +36 -0
  89. package/core/search/types.js +61 -0
  90. package/core/search/worker-client.js +56 -0
  91. package/core/search/worker.js +20 -0
  92. package/dist/chunks/a11y-utils-IRC7LOPF.js +16 -0
  93. package/dist/chunks/attributes-3BZLI7XF.js +364 -0
  94. package/dist/chunks/attributes-4N5JP4CG.js +364 -0
  95. package/dist/chunks/attributes-5Q2WXGRC.js +374 -0
  96. package/dist/chunks/attributes-AIR7SVLK.js +364 -0
  97. package/dist/chunks/attributes-BGRN5XZO.js +364 -0
  98. package/dist/chunks/attributes-BVSQAYLR.js +364 -0
  99. package/dist/chunks/attributes-CDYFUY7Y.js +364 -0
  100. package/dist/chunks/attributes-JMYJZBPE.js +364 -0
  101. package/dist/chunks/attributes-R5JY3X4O.js +374 -0
  102. package/dist/chunks/attributes-STYCS3O5.js +391 -0
  103. package/dist/chunks/attributes-TNSPQTHX.js +374 -0
  104. package/dist/chunks/attributes-TPANLMLF.js +391 -0
  105. package/dist/chunks/blade-LIQLVKZQ.js +19 -0
  106. package/dist/chunks/browser-MRKYZPEH.js +1149 -0
  107. package/dist/chunks/chunk-2354NEBP.js +109 -0
  108. package/dist/chunks/chunk-2VNA7G7S.js +109 -0
  109. package/dist/chunks/chunk-42VVPW6N.js +132 -0
  110. package/dist/chunks/chunk-7FFAMRFV.js +44 -0
  111. package/dist/chunks/chunk-7MCGPHVC.js +69 -0
  112. package/dist/chunks/chunk-AQLRJSGG.js +109 -0
  113. package/dist/chunks/chunk-EWPSDMQT.js +109 -0
  114. package/dist/chunks/chunk-F7OLHTGX.js +22 -0
  115. package/dist/chunks/chunk-J472ERN2.js +242 -0
  116. package/dist/chunks/chunk-LA7264K4.js +85 -0
  117. package/dist/chunks/chunk-M5CHQVP6.js +61 -0
  118. package/dist/chunks/chunk-MKZP2TBH.js +89 -0
  119. package/dist/chunks/chunk-QTJJ3DPO.js +109 -0
  120. package/dist/chunks/chunk-RDE3QE7Z.js +89 -0
  121. package/dist/chunks/chunk-RSMRR27R.js +109 -0
  122. package/dist/chunks/chunk-RZQVWFHW.js +109 -0
  123. package/dist/chunks/chunk-SRL6EWHP.js +109 -0
  124. package/dist/chunks/chunk-U4XHMZ7D.js +109 -0
  125. package/dist/chunks/chunk-V5YIUA6G.js +109 -0
  126. package/dist/chunks/chunk-XIET2VSZ.js +109 -0
  127. package/dist/chunks/chunk-XYLJ2GCB.js +205 -0
  128. package/dist/chunks/chunk-Z4JYQ2XX.js +51 -0
  129. package/dist/chunks/chunk-ZPSPKUYD.js +109 -0
  130. package/dist/chunks/css-MQ5YU77P.js +28 -0
  131. package/dist/chunks/highlight-GJHHV4KM.js +37 -0
  132. package/dist/chunks/highlight-XTHRKBA3.js +37 -0
  133. package/dist/chunks/html-ZODC4DLQ.js +20 -0
  134. package/dist/chunks/js-MNSNYTJU.js +7 -0
  135. package/dist/chunks/json-VEM2HFH3.js +17 -0
  136. package/dist/chunks/markdown-E7OPGS3S.js +19 -0
  137. package/dist/chunks/php-MLL7T3LT.js +41 -0
  138. package/dist/chunks/plain-LJJDC5TN.js +8 -0
  139. package/dist/chunks/runtime-entry.js +14 -0
  140. package/dist/chunks/shell-QTRK4U4E.js +35 -0
  141. package/dist/chunks/sql-PPWLHGJ2.js +23 -0
  142. package/dist/chunks/typescript-JT3CCYWL.js +30 -0
  143. package/dist/chunks/velin-accordion-FBIPAEXG.js +105 -0
  144. package/dist/chunks/velin-accordion-QAQO7BI7.js +117 -0
  145. package/dist/chunks/velin-announcer-PVTXXCWR.js +33 -0
  146. package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +86 -0
  147. package/dist/chunks/velin-bottom-nav-7GEMPIM6.js +86 -0
  148. package/dist/chunks/velin-bottom-nav-CTU6FFZV.js +101 -0
  149. package/dist/chunks/velin-bottom-nav-N3DFQR66.js +86 -0
  150. package/dist/chunks/velin-carousel-Y5VCOABZ.js +213 -0
  151. package/dist/chunks/velin-carousel-ZTBANFQQ.js +213 -0
  152. package/dist/chunks/velin-code-block-ASUBTAQV.js +119 -0
  153. package/dist/chunks/velin-code-block-CIAURDRJ.js +132 -0
  154. package/dist/chunks/velin-code-block-TSUKPY4C.js +123 -0
  155. package/dist/chunks/velin-code-block-Y6CM726Q.js +119 -0
  156. package/dist/chunks/velin-collapse-5XYBUIID.js +80 -0
  157. package/dist/chunks/velin-combobox-2KDTCQ7N.js +155 -0
  158. package/dist/chunks/velin-combobox-NXS4QB4R.js +155 -0
  159. package/dist/chunks/velin-combobox-UGA56HP3.js +155 -0
  160. package/dist/chunks/velin-command-CKDNO4BW.js +148 -0
  161. package/dist/chunks/velin-command-M7RNHUPR.js +136 -0
  162. package/dist/chunks/velin-command-ONKO2A3J.js +136 -0
  163. package/dist/chunks/velin-command-TMLSRGIU.js +136 -0
  164. package/dist/chunks/velin-copy-G2TZ5YBB.js +81 -0
  165. package/dist/chunks/velin-copy-NYDBOKXT.js +81 -0
  166. package/dist/chunks/velin-copy-T5KDTDXP.js +81 -0
  167. package/dist/chunks/velin-countdown-4ZVDGK4R.js +101 -0
  168. package/dist/chunks/velin-countdown-5XSTN3BH.js +101 -0
  169. package/dist/chunks/velin-countdown-7AIY66CU.js +101 -0
  170. package/dist/chunks/velin-counter-ISCTEAHI.js +118 -0
  171. package/dist/chunks/velin-counter-L5FYJF7A.js +121 -0
  172. package/dist/chunks/velin-dialog-D2GUHSCD.js +144 -0
  173. package/dist/chunks/velin-dialog-ELFOZIXZ.js +152 -0
  174. package/dist/chunks/velin-dialog-GTTZI564.js +147 -0
  175. package/dist/chunks/velin-dialog-IJLFDXAJ.js +144 -0
  176. package/dist/chunks/velin-dialog-TNS3WXMB.js +144 -0
  177. package/dist/chunks/velin-drawer-BE6TYN3H.js +130 -0
  178. package/dist/chunks/velin-drawer-DLL2GLT6.js +130 -0
  179. package/dist/chunks/velin-drawer-MJS6WCF7.js +130 -0
  180. package/dist/chunks/velin-dropdown-PLUIFA5M.js +172 -0
  181. package/dist/chunks/velin-email-N5B5ZYTE.js +90 -0
  182. package/dist/chunks/velin-email-NTM6DG3V.js +90 -0
  183. package/dist/chunks/velin-email-RBX6ZR4S.js +90 -0
  184. package/dist/chunks/velin-haptic-4QQTM3RK.js +50 -0
  185. package/dist/chunks/velin-icon-7M76DOPB.js +164 -0
  186. package/dist/chunks/velin-icon-KZO3IEHG.js +164 -0
  187. package/dist/chunks/velin-icon-WTFPG2DD.js +191 -0
  188. package/dist/chunks/velin-icon-ZTSKUOVN.js +193 -0
  189. package/dist/chunks/velin-lightbox-6E7CAATP.js +149 -0
  190. package/dist/chunks/velin-lightbox-I75U6JF4.js +140 -0
  191. package/dist/chunks/velin-lightbox-QOTB4PRL.js +140 -0
  192. package/dist/chunks/velin-lightbox-UCD6N7HF.js +140 -0
  193. package/dist/chunks/velin-live-dot-RJHX2DGY.js +74 -0
  194. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +67 -0
  195. package/dist/chunks/velin-menubar-I426AED2.js +86 -0
  196. package/dist/chunks/velin-menubar-J66JXRWW.js +86 -0
  197. package/dist/chunks/velin-menubar-SFEXJE56.js +86 -0
  198. package/dist/chunks/velin-modal-2HOBXE6F.js +176 -0
  199. package/dist/chunks/velin-modal-5HYNNNUI.js +176 -0
  200. package/dist/chunks/velin-modal-AEOTZ67O.js +177 -0
  201. package/dist/chunks/velin-modal-GLI2XZZB.js +176 -0
  202. package/dist/chunks/velin-persist-DFPL3QP4.js +110 -0
  203. package/dist/chunks/velin-popover-EXINRIGJ.js +145 -0
  204. package/dist/chunks/velin-popover-HQW6Q2Y6.js +172 -0
  205. package/dist/chunks/velin-popover-OXX7MRZ6.js +145 -0
  206. package/dist/chunks/velin-popover-T72HK3DF.js +151 -0
  207. package/dist/chunks/velin-popover-YKCCROJG.js +145 -0
  208. package/dist/chunks/velin-progress-ring-E4YRLZHH.js +66 -0
  209. package/dist/chunks/velin-rating-6CDBI6DG.js +91 -0
  210. package/dist/chunks/velin-rating-N4DI2XNL.js +91 -0
  211. package/dist/chunks/velin-rating-XRQJV4LO.js +91 -0
  212. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +58 -0
  213. package/dist/chunks/velin-scroll-top-OHYVVHHY.js +58 -0
  214. package/dist/chunks/velin-scrollspy-OKCT4FDV.js +50 -0
  215. package/dist/chunks/velin-search-2XRQFBCS.js +556 -0
  216. package/dist/chunks/velin-search-4YHJWYSS.js +556 -0
  217. package/dist/chunks/velin-search-7B4KJ6TX.js +557 -0
  218. package/dist/chunks/velin-search-LWHY23Q5.js +474 -0
  219. package/dist/chunks/velin-secure-field-6PV7RZDJ.js +95 -0
  220. package/dist/chunks/velin-secure-field-H7FSBUJW.js +95 -0
  221. package/dist/chunks/velin-secure-field-OFNAXCDP.js +95 -0
  222. package/dist/chunks/velin-segmented-control-EKL4E3BL.js +109 -0
  223. package/dist/chunks/velin-segmented-control-GYD5BIXQ.js +109 -0
  224. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +109 -0
  225. package/dist/chunks/velin-sheet-3OGI4HD7.js +119 -0
  226. package/dist/chunks/velin-sheet-OUK6572T.js +119 -0
  227. package/dist/chunks/velin-sheet-R2Y67X6H.js +119 -0
  228. package/dist/chunks/velin-sparkline-GVEANJVW.js +184 -0
  229. package/dist/chunks/velin-sparkline-KDA3GQAN.js +162 -0
  230. package/dist/chunks/velin-sparkline-XVTFC6GE.js +181 -0
  231. package/dist/chunks/velin-stepper-2ZIHLKGM.js +141 -0
  232. package/dist/chunks/velin-stepper-7ECRUYHD.js +148 -0
  233. package/dist/chunks/velin-stepper-FYEUEWE6.js +141 -0
  234. package/dist/chunks/velin-stepper-X54WGHDG.js +141 -0
  235. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +133 -0
  236. package/dist/chunks/velin-tabs-5UQ5ZVMV.js +138 -0
  237. package/dist/chunks/velin-theme-toggle-32J2CBNC.js +291 -0
  238. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +285 -0
  239. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +285 -0
  240. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +291 -0
  241. package/dist/chunks/velin-toast-OMMOA2DK.js +109 -0
  242. package/dist/chunks/velin-toast-RCZ4CSUC.js +109 -0
  243. package/dist/chunks/velin-toast-RSF2IHT3.js +113 -0
  244. package/dist/chunks/velin-toast-WEUBTJG6.js +109 -0
  245. package/dist/chunks/velin-tooltip-664IOHZA.js +112 -0
  246. package/dist/chunks/velin-tooltip-BDHGRTQB.js +112 -0
  247. package/dist/chunks/velin-tooltip-HVUOKNVX.js +112 -0
  248. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +103 -0
  249. package/dist/chunks/worker-client-R6DBYPFT.js +46 -0
  250. package/dist/llms.test.txt +40 -0
  251. package/dist/llms.txt +40 -0
  252. package/dist/search-index.json +1773 -0
  253. package/dist/search-index.test.json +1773 -0
  254. package/dist/themes/brutalist.min.css +1 -1
  255. package/dist/themes/midnight.min.css +1 -1
  256. package/dist/themes/pastel.min.css +1 -1
  257. package/dist/themes/retro.min.css +1 -1
  258. package/dist/themes/sunset.min.css +1 -1
  259. package/dist/velin-agent.json +684 -0
  260. package/dist/velin-agent.test.json +684 -0
  261. package/dist/velinstyle-components.iife.js +7715 -3515
  262. package/dist/velinstyle-components.js +7087 -2859
  263. package/dist/velinstyle-components.min.js +196 -109
  264. package/dist/velinstyle.css +604 -65
  265. package/dist/velinstyle.d.ts +54 -0
  266. package/dist/velinstyle.min.css +1 -1
  267. package/examples/search-index.schema.json +33 -0
  268. package/package.json +56 -10
  269. package/src/a11y/authentication.css +37 -0
  270. package/src/a11y/consistent-help.css +22 -0
  271. package/src/a11y/dragging-alternatives.css +30 -0
  272. package/src/a11y/focus-appearance.css +20 -0
  273. package/src/a11y/high-contrast-aaa.css +16 -26
  274. package/src/a11y/skip-link.css +3 -1
  275. package/src/a11y/sr-only.css +1 -1
  276. package/src/base/reset.css +0 -36
  277. package/src/base/wc-placeholder.css +102 -0
  278. package/src/components/attributes.css +42 -0
  279. package/src/components/highlight.css +182 -0
  280. package/src/components/input-group.css +1 -2
  281. package/src/components/nav.css +2 -3
  282. package/src/components/search.css +95 -0
  283. package/src/components/stepper.css +2 -4
  284. package/src/components/timeline.css +1 -2
  285. package/src/components/tooltip.css +2 -4
  286. package/src/layout/container.css +5 -5
  287. package/src/layout/grid.css +8 -8
  288. package/src/layout/patterns.css +5 -5
  289. package/src/themes/brutalist.css +2 -11
  290. package/src/themes/corporate.css +0 -9
  291. package/src/themes/earth.css +0 -9
  292. package/src/themes/forest.css +0 -9
  293. package/src/themes/midnight.css +1 -10
  294. package/src/themes/neon.css +0 -9
  295. package/src/themes/nordic.css +0 -9
  296. package/src/themes/ocean.css +0 -9
  297. package/src/themes/pastel.css +1 -10
  298. package/src/themes/retro.css +2 -11
  299. package/src/themes/sharp.css +0 -7
  300. package/src/themes/soft.css +0 -7
  301. package/src/themes/sunset.css +1 -10
  302. package/src/tokens/color.css +45 -46
  303. package/src/tokens/fonts.css +10 -0
  304. package/src/tokens/typography.css +4 -5
  305. package/src/utilities/animation.css +2 -2
  306. package/src/utilities/display.css +3 -3
  307. package/src/utilities/divide.css +2 -6
  308. package/src/utilities/responsive.css +4 -4
  309. package/src/utilities/safe-area.css +1 -1
  310. package/src/utilities/scroll-animation.css +34 -0
  311. package/src/utilities/spacing.css +17 -8
  312. package/src/utilities/text.css +4 -1
  313. package/src/velinstyle.css +9 -0
@@ -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
+ }
package/cli/index.js CHANGED
@@ -15,7 +15,7 @@ const LAYERS = ['tokens', 'reset', 'base', 'a11y', 'layout', 'components', 'util
15
15
 
16
16
  const LAYER_FILES = {
17
17
  tokens: [
18
- 'tokens/color.css', 'tokens/spacing.css', 'tokens/typography.css',
18
+ 'tokens/fonts.css', 'tokens/color.css', 'tokens/spacing.css', 'tokens/typography.css',
19
19
  'tokens/radius.css', 'tokens/shadow.css', 'tokens/motion.css',
20
20
  'tokens/z-index.css', 'tokens/aspect-ratio.css',
21
21
  ],
@@ -25,6 +25,8 @@ const LAYER_FILES = {
25
25
  'a11y/sr-only.css', 'a11y/skip-link.css', 'a11y/reduced-motion.css',
26
26
  'a11y/forced-colors.css', 'a11y/skeleton.css', 'a11y/preferences.css',
27
27
  'a11y/focus-not-obscured.css', 'a11y/target-size.css', 'a11y/high-contrast-aaa.css',
28
+ 'a11y/authentication.css', 'a11y/consistent-help.css', 'a11y/dragging-alternatives.css',
29
+ 'a11y/focus-appearance.css',
28
30
  ],
29
31
  security: ['a11y/security.css'],
30
32
  layout: [
@@ -47,8 +49,9 @@ const LAYER_FILES = {
47
49
  'utilities/position.css', 'utilities/animation.css', 'utilities/gradient.css',
48
50
  'utilities/print.css', 'utilities/responsive.css', 'utilities/divide.css',
49
51
  'utilities/scroll.css', 'utilities/color-mix.css', 'utilities/scroll-animation.css',
50
- 'utilities/view-transition.css', 'utilities/scope.css', 'utilities/anchor.css',
51
- 'utilities/filter.css', 'utilities/container-style.css', 'utilities/state.css',
52
+ 'utilities/view-transition.css', 'utilities/scope.css', 'utilities/anchor.css',
53
+ 'utilities/filter.css', 'utilities/filter-effects.css', 'utilities/chart-animation.css',
54
+ 'utilities/container-style.css', 'utilities/state.css',
52
55
  'utilities/safe-area.css',
53
56
  ],
54
57
  helpers: ['helpers/helpers.css'],
@@ -80,7 +83,7 @@ function hasFlag(flag, alias) {
80
83
 
81
84
  function help() {
82
85
  console.log(`
83
- ${C.bold('VelinStyle CLI')} v0.8.0
86
+ ${C.bold('VelinStyle CLI')} v0.9.0
84
87
 
85
88
  ${C.bold('Usage:')}
86
89
  velinstyle init Create velinstyle.config.js
@@ -93,7 +96,12 @@ function help() {
93
96
  velinstyle blueprint [name] Print HTML blueprint (run: velinstyle blueprint list)
94
97
  velinstyle scaffold "<prompt>" Generate layout HTML from a text description
95
98
  velinstyle layout <sub> Responsive layout audit and fixes
99
+ velinstyle perf <sub> Performance audit (images, scripts) with --fix
96
100
  velinstyle tokens build Generate CSS variables from tokens.json
101
+ velinstyle tokens validate Validate tokens.json schema
102
+ velinstyle docs generate Auto-generate Markdown API reference
103
+ velinstyle meta Build agent context (velin-agent.json, llms.txt)
104
+ velinstyle search index Build JSON search index for VelinSearch
97
105
 
98
106
  ${C.bold('Icons subcommands:')}
99
107
  icons list Show available icon providers
@@ -120,14 +128,29 @@ function help() {
120
128
  velinstyle layout suggest [path] Audit with fix suggestions
121
129
  velinstyle layout fix [path] Apply safe fixes (--dry-run default, --write)
122
130
 
131
+ ${C.bold('Performance (0.9.0):')}
132
+ velinstyle perf audit [path] Report CLS, lazy-load, script defer issues
133
+ velinstyle perf suggest [path] Same as audit with fix hints
134
+ velinstyle perf fix [path] Apply safe fixes (--write)
135
+
123
136
  ${C.bold('Tokens:')}
124
137
  velinstyle tokens build [--input <path>] [--output, -o <file>]
138
+ velinstyle tokens validate [--input <path>]
139
+
140
+ ${C.bold('Docs (0.9.0):')}
141
+ velinstyle docs generate [--scope all|components|tokens|utilities|cli|rules|a11y|meta] [--out docs/generated]
142
+ velinstyle meta [--out dist/velin-agent.json] [--llms-out dist/llms.txt] [--base-url URL]
143
+ velinstyle meta page <file.html> [--write]
144
+
145
+ ${C.bold('Search:')}
146
+ velinstyle search index [--out dist/search-index.json] [--extra-html dir1,dir2]
125
147
 
126
148
  ${C.bold('Scan options:')}
127
149
  --fix Auto-fix safe issues (writes files)
128
150
  --fix-dry-run Show files that would be auto-fixed; no write
129
151
  --fix-lang <code> Default lang for a11y/html-lang fix (default: de)
130
152
  --severity <level> Minimum severity: error, warning, info
153
+ --only <category> Filter: security, pii, a11y, css, perf
131
154
 
132
155
  ${C.bold('Prefix options (velinstyle prefix):')}
133
156
  --write Write files (default is dry-run)
@@ -470,13 +493,64 @@ async function tokensBuildCmd() {
470
493
  }
471
494
  }
472
495
 
496
+ async function tokensValidateCmd() {
497
+ const input = getArg('--input') || 'examples/tokens.sample.json';
498
+ const { validateTokensJson } = await import('./tokens-validate.js');
499
+ const result = validateTokensJson(resolve(input));
500
+ if (result.ok) {
501
+ console.log(C.green(`Valid: ${resolve(input)}`));
502
+ process.exit(0);
503
+ }
504
+ console.log(C.red(`Invalid: ${resolve(input)}`));
505
+ result.errors.forEach((e) => console.log(` - ${e}`));
506
+ process.exit(1);
507
+ }
508
+
473
509
  async function tokensCmd() {
474
510
  const sub = args[1];
475
511
  if (sub === 'build') {
476
512
  await tokensBuildCmd();
513
+ } else if (sub === 'validate') {
514
+ await tokensValidateCmd();
477
515
  } else {
478
- console.log('Usage: velinstyle tokens build [--input tokens.json] [--output out.css]');
516
+ console.log('Usage: velinstyle tokens build|validate [--input tokens.json] [--output, -o <file>]');
517
+ }
518
+ }
519
+
520
+ async function perfCmd() {
521
+ const sub = args[1] || 'audit';
522
+ const rawTarget = args[2] && !args[2].startsWith('-') ? args[2] : '.';
523
+ const targetPath = resolve(rawTarget);
524
+ const asJson = hasFlag('--json');
525
+ const write = hasFlag('--write');
526
+ const dryRun = hasFlag('--dry-run') || !write;
527
+
528
+ const { auditPath, formatTextReport, fixPath } = await import('./perf-audit.js');
529
+
530
+ if (sub === 'fix') {
531
+ const result = fixPath(targetPath, { write, dryRun });
532
+ if (asJson) {
533
+ console.log(JSON.stringify(result, null, 2));
534
+ return;
535
+ }
536
+ if (result.changes.length === 0) {
537
+ console.log(C.green('No safe performance fixes to apply.'));
538
+ return;
539
+ }
540
+ for (const c of result.changes) {
541
+ console.log(`${dryRun ? '[dry-run] ' : ''}${c.file}`);
542
+ c.changes.forEach((ch) => console.log(C.dim(` - ${ch}`)));
543
+ }
544
+ return;
479
545
  }
546
+
547
+ const { issues, files } = auditPath(targetPath);
548
+ if (asJson) {
549
+ console.log(JSON.stringify({ files, issues }, null, 2));
550
+ return;
551
+ }
552
+ console.log(formatTextReport(issues, files));
553
+ process.exit(issues.some((x) => x.severity === 'error') ? 1 : 0);
480
554
  }
481
555
 
482
556
  async function prefixCmd() {
@@ -608,6 +682,44 @@ async function layoutCmd() {
608
682
  process.exit(issues.some((x) => x.severity === 'error') ? 1 : 0);
609
683
  }
610
684
 
685
+ async function docsCmd() {
686
+ const sub = args[1];
687
+ if (sub === 'generate') {
688
+ const scope = getArg('--scope') || 'all';
689
+ const out = getArg('--out') || join(PKG_ROOT, 'docs', 'generated');
690
+ const { generateDocs } = await import('./docs-generate.js');
691
+ const result = await generateDocs({ scope, outDir: resolve(out), searchIndex: true });
692
+ if (!result.ok) {
693
+ console.log(C.red(result.error));
694
+ process.exit(1);
695
+ }
696
+ console.log(C.green(`Generated ${result.written} file(s) → ${resolve(out)}`));
697
+ return;
698
+ }
699
+ console.log('Usage: velinstyle docs generate [--scope all|components|tokens|utilities|cli|rules|a11y|meta] [--out <dir>]');
700
+ }
701
+
702
+ async function metaCmd() {
703
+ const { metaMain } = await import('./meta.js');
704
+ await metaMain(process.argv.slice(2));
705
+ }
706
+
707
+ async function searchCmd() {
708
+ const sub = args[1];
709
+ if (sub === 'index') {
710
+ const out = getArg('--out') || join(PKG_ROOT, 'dist', 'search-index.json');
711
+ const extra = getArg('--extra-html');
712
+ const { buildSearchIndex } = await import('./search-index.js');
713
+ const result = buildSearchIndex({
714
+ outFile: resolve(out),
715
+ extraHtmlDirs: extra ? extra.split(',').map((p) => resolve(p.trim())) : [],
716
+ });
717
+ console.log(C.green(`Search index: ${result.count} entries → ${result.outFile}`));
718
+ return;
719
+ }
720
+ console.log('Usage: velinstyle search index [--out <file>] [--extra-html dir1,dir2]');
721
+ }
722
+
611
723
  async function scanCmd() {
612
724
  const targetPath = args[1] && !args[1].startsWith('-') ? resolve(args[1]) : resolve('.');
613
725
  const format = getArg('--format') || 'text';
@@ -647,6 +759,10 @@ switch (command) {
647
759
  case 'prefix': await prefixCmd(); break;
648
760
  case 'scaffold': await scaffoldCmd(); break;
649
761
  case 'layout': await layoutCmd(); break;
762
+ case 'perf': await perfCmd(); break;
763
+ case 'docs': await docsCmd(); break;
764
+ case 'meta': await metaCmd(); break;
765
+ case 'search': await searchCmd(); break;
650
766
  case '--help': case '-h': help(); break;
651
767
  default: help(); break;
652
768
  }
package/cli/meta.js ADDED
@@ -0,0 +1,97 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
2
+ import { join, dirname, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { buildAgentBundle, buildLlmsTxt, buildPageMeta, serializePageMetaScript } from '../core/meta/index.js';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const PKG_ROOT = join(__dirname, '..');
8
+
9
+ /**
10
+ * @param {object} [options]
11
+ * @param {string} [options.outFile]
12
+ * @param {string} [options.llmsFile]
13
+ * @param {string} [options.baseUrl]
14
+ * @param {boolean} [options.llms]
15
+ */
16
+ export async function buildMeta(options = {}) {
17
+ const outFile = options.outFile || join(PKG_ROOT, 'dist', 'velin-agent.json');
18
+ const llmsFile = options.llmsFile || join(PKG_ROOT, 'dist', 'llms.txt');
19
+ const bundle = await buildAgentBundle({ pkgRoot: PKG_ROOT });
20
+
21
+ mkdirSync(dirname(outFile), { recursive: true });
22
+ writeFileSync(outFile, JSON.stringify(bundle, null, 2), 'utf-8');
23
+
24
+ const written = [outFile];
25
+
26
+ if (options.llms !== false) {
27
+ const llms = buildLlmsTxt(bundle, options.baseUrl || 'https://velinstyle.info');
28
+ writeFileSync(llmsFile, llms, 'utf-8');
29
+ written.push(llmsFile);
30
+ }
31
+
32
+ return { ok: true, bundle, written, count: written.length };
33
+ }
34
+
35
+ /**
36
+ * @param {string} htmlPath
37
+ * @param {object} [options]
38
+ */
39
+ export function metaPage(htmlPath, options = {}) {
40
+ const abs = resolve(htmlPath);
41
+ if (!existsSync(abs)) {
42
+ return { ok: false, error: `File not found: ${abs}` };
43
+ }
44
+ const html = readFileSync(abs, 'utf-8');
45
+ const rel = htmlPath.replace(/\\/g, '/');
46
+ const meta = buildPageMeta(html, rel, PKG_ROOT);
47
+ const script = serializePageMetaScript(meta);
48
+
49
+ if (options.write) {
50
+ if (html.includes('id="velin-meta"')) {
51
+ const updated = html.replace(
52
+ /<script[^>]*id=["']velin-meta["'][^>]*>[\s\S]*?<\/script>/i,
53
+ script,
54
+ );
55
+ writeFileSync(abs, updated, 'utf-8');
56
+ } else if (/<\/head>/i.test(html)) {
57
+ writeFileSync(abs, html.replace(/<\/head>/i, ` ${script}\n</head>`), 'utf-8');
58
+ } else {
59
+ return { ok: false, error: 'No </head> or existing velin-meta block found' };
60
+ }
61
+ }
62
+
63
+ return { ok: true, meta, script };
64
+ }
65
+
66
+ export async function metaMain(argv = process.argv.slice(2)) {
67
+ const pageIdx = argv.indexOf('page');
68
+ if (pageIdx !== -1 && argv[pageIdx + 1]) {
69
+ const write = argv.includes('--write');
70
+ const result = metaPage(argv[pageIdx + 1], { write });
71
+ if (!result.ok) {
72
+ console.error(result.error);
73
+ process.exit(1);
74
+ }
75
+ if (write) {
76
+ console.log(`Updated velin-meta in ${argv[pageIdx + 1]}`);
77
+ } else {
78
+ console.log(result.script);
79
+ }
80
+ return;
81
+ }
82
+
83
+ const outIdx = argv.indexOf('--out');
84
+ const llmsIdx = argv.indexOf('--llms-out');
85
+ const baseIdx = argv.indexOf('--base-url');
86
+ const noLlms = argv.includes('--no-llms');
87
+
88
+ const result = await buildMeta({
89
+ outFile: outIdx !== -1 && argv[outIdx + 1] ? resolve(argv[outIdx + 1]) : undefined,
90
+ llmsFile: llmsIdx !== -1 && argv[llmsIdx + 1] ? resolve(argv[llmsIdx + 1]) : undefined,
91
+ baseUrl: baseIdx !== -1 && argv[baseIdx + 1] ? argv[baseIdx + 1] : undefined,
92
+ llms: !noLlms,
93
+ });
94
+
95
+ console.log(`Velin-Meta: wrote ${result.count} file(s)`);
96
+ for (const p of result.written) console.log(` ${p}`);
97
+ }