@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.
- package/README.de.md +135 -246
- package/README.md +134 -245
- package/cli/blueprints/onboarding.html +2 -2
- package/cli/cli-manifest.json +97 -0
- package/cli/docgen/extract-a11y.js +89 -0
- package/cli/docgen/extract-attributes.js +95 -0
- package/cli/docgen/extract-cli.js +50 -0
- package/cli/docgen/extract-components.js +175 -0
- package/cli/docgen/extract-meta.js +32 -0
- package/cli/docgen/extract-rules.js +76 -0
- package/cli/docgen/extract-tokens.js +79 -0
- package/cli/docgen/extract-utilities.js +75 -0
- package/cli/docgen/markdown.js +43 -0
- package/cli/docs-generate.js +196 -0
- package/cli/index.js +121 -5
- package/cli/meta.js +97 -0
- package/cli/perf-audit.js +174 -0
- package/cli/pii-scanner.js +134 -0
- package/cli/scanner-rules-data.js +62 -0
- package/cli/scanner.js +68 -1
- package/cli/search-index.js +163 -0
- package/cli/tokens-build.js +21 -1
- package/cli/tokens-validate.js +69 -0
- package/components/a11y-entry.js +42 -0
- package/components/a11y-utils.js +71 -0
- package/components/focus-manager.js +45 -8
- package/components/index.js +22 -12
- package/components/runtime/component-loaders.js +43 -0
- package/components/runtime/index.js +77 -0
- package/components/runtime-entry.js +10 -0
- package/components/sanitize.js +135 -54
- package/components/velin-accordion.js +12 -0
- package/components/velin-bottom-nav.js +19 -0
- package/components/velin-carousel.js +2 -2
- package/components/velin-code-block.js +142 -0
- package/components/velin-command.js +15 -0
- package/components/velin-copy.js +18 -5
- package/components/velin-counter.js +3 -0
- package/components/velin-dialog.js +9 -1
- package/components/velin-email.js +94 -0
- package/components/velin-icon.js +65 -22
- package/components/velin-lightbox.js +8 -3
- package/components/velin-live-dot.js +5 -0
- package/components/velin-modal.js +6 -3
- package/components/velin-popover.js +34 -2
- package/components/velin-reveal.js +7 -65
- package/components/velin-scroll-top.js +1 -1
- package/components/velin-search.js +267 -0
- package/components/velin-secure-field.js +99 -0
- package/components/velin-sparkline.js +27 -7
- package/components/{velin-stepper-wc.js → velin-stepper.js} +37 -8
- package/components/velin-theme-toggle.js +12 -5
- package/components/velin-toast.js +4 -0
- package/components/{velin-tooltip-wc.js → velin-tooltip.js} +22 -3
- package/core/a11y/component-contracts.json +221 -0
- package/core/attributes/index.js +6 -0
- package/core/attributes/registry.js +268 -0
- package/core/highlight/highlight.js +114 -0
- package/core/highlight/index.js +29 -0
- package/core/highlight/languages/_utils.js +52 -0
- package/core/highlight/languages/blade.js +16 -0
- package/core/highlight/languages/css.js +26 -0
- package/core/highlight/languages/html.js +17 -0
- package/core/highlight/languages/js.js +58 -0
- package/core/highlight/languages/json.js +14 -0
- package/core/highlight/languages/markdown.js +16 -0
- package/core/highlight/languages/php.js +39 -0
- package/core/highlight/languages/plain.js +7 -0
- package/core/highlight/languages/shell.js +33 -0
- package/core/highlight/languages/sql.js +20 -0
- package/core/highlight/languages/typescript.js +28 -0
- package/core/highlight/observe.js +53 -0
- package/core/highlight/registry.js +107 -0
- package/core/highlight/render.js +35 -0
- package/core/highlight/types.js +28 -0
- package/core/meta/build.js +293 -0
- package/core/meta/index.js +17 -0
- package/core/meta/schema.js +49 -0
- package/core/motion/effects.js +54 -0
- package/core/motion/index.js +76 -0
- package/core/motion/scheduler.js +72 -0
- package/core/motion/scroll.js +32 -0
- package/core/motion/stagger.js +24 -0
- package/core/search/docs-url.js +96 -0
- package/core/search/engine.js +139 -0
- package/core/search/highlight.js +48 -0
- package/core/search/index.js +126 -0
- package/core/search/providers.js +36 -0
- package/core/search/types.js +61 -0
- package/core/search/worker-client.js +56 -0
- package/core/search/worker.js +20 -0
- package/dist/chunks/a11y-utils-IRC7LOPF.js +16 -0
- package/dist/chunks/attributes-3BZLI7XF.js +364 -0
- package/dist/chunks/attributes-4N5JP4CG.js +364 -0
- package/dist/chunks/attributes-5Q2WXGRC.js +374 -0
- package/dist/chunks/attributes-AIR7SVLK.js +364 -0
- package/dist/chunks/attributes-BGRN5XZO.js +364 -0
- package/dist/chunks/attributes-BVSQAYLR.js +364 -0
- package/dist/chunks/attributes-CDYFUY7Y.js +364 -0
- package/dist/chunks/attributes-JMYJZBPE.js +364 -0
- package/dist/chunks/attributes-R5JY3X4O.js +374 -0
- package/dist/chunks/attributes-STYCS3O5.js +391 -0
- package/dist/chunks/attributes-TNSPQTHX.js +374 -0
- package/dist/chunks/attributes-TPANLMLF.js +391 -0
- package/dist/chunks/blade-LIQLVKZQ.js +19 -0
- package/dist/chunks/browser-MRKYZPEH.js +1149 -0
- package/dist/chunks/chunk-2354NEBP.js +109 -0
- package/dist/chunks/chunk-2VNA7G7S.js +109 -0
- package/dist/chunks/chunk-42VVPW6N.js +132 -0
- package/dist/chunks/chunk-7FFAMRFV.js +44 -0
- package/dist/chunks/chunk-7MCGPHVC.js +69 -0
- package/dist/chunks/chunk-AQLRJSGG.js +109 -0
- package/dist/chunks/chunk-EWPSDMQT.js +109 -0
- package/dist/chunks/chunk-F7OLHTGX.js +22 -0
- package/dist/chunks/chunk-J472ERN2.js +242 -0
- package/dist/chunks/chunk-LA7264K4.js +85 -0
- package/dist/chunks/chunk-M5CHQVP6.js +61 -0
- package/dist/chunks/chunk-MKZP2TBH.js +89 -0
- package/dist/chunks/chunk-QTJJ3DPO.js +109 -0
- package/dist/chunks/chunk-RDE3QE7Z.js +89 -0
- package/dist/chunks/chunk-RSMRR27R.js +109 -0
- package/dist/chunks/chunk-RZQVWFHW.js +109 -0
- package/dist/chunks/chunk-SRL6EWHP.js +109 -0
- package/dist/chunks/chunk-U4XHMZ7D.js +109 -0
- package/dist/chunks/chunk-V5YIUA6G.js +109 -0
- package/dist/chunks/chunk-XIET2VSZ.js +109 -0
- package/dist/chunks/chunk-XYLJ2GCB.js +205 -0
- package/dist/chunks/chunk-Z4JYQ2XX.js +51 -0
- package/dist/chunks/chunk-ZPSPKUYD.js +109 -0
- package/dist/chunks/css-MQ5YU77P.js +28 -0
- package/dist/chunks/highlight-GJHHV4KM.js +37 -0
- package/dist/chunks/highlight-XTHRKBA3.js +37 -0
- package/dist/chunks/html-ZODC4DLQ.js +20 -0
- package/dist/chunks/js-MNSNYTJU.js +7 -0
- package/dist/chunks/json-VEM2HFH3.js +17 -0
- package/dist/chunks/markdown-E7OPGS3S.js +19 -0
- package/dist/chunks/php-MLL7T3LT.js +41 -0
- package/dist/chunks/plain-LJJDC5TN.js +8 -0
- package/dist/chunks/runtime-entry.js +14 -0
- package/dist/chunks/shell-QTRK4U4E.js +35 -0
- package/dist/chunks/sql-PPWLHGJ2.js +23 -0
- package/dist/chunks/typescript-JT3CCYWL.js +30 -0
- package/dist/chunks/velin-accordion-FBIPAEXG.js +105 -0
- package/dist/chunks/velin-accordion-QAQO7BI7.js +117 -0
- package/dist/chunks/velin-announcer-PVTXXCWR.js +33 -0
- package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +86 -0
- package/dist/chunks/velin-bottom-nav-7GEMPIM6.js +86 -0
- package/dist/chunks/velin-bottom-nav-CTU6FFZV.js +101 -0
- package/dist/chunks/velin-bottom-nav-N3DFQR66.js +86 -0
- package/dist/chunks/velin-carousel-Y5VCOABZ.js +213 -0
- package/dist/chunks/velin-carousel-ZTBANFQQ.js +213 -0
- package/dist/chunks/velin-code-block-ASUBTAQV.js +119 -0
- package/dist/chunks/velin-code-block-CIAURDRJ.js +132 -0
- package/dist/chunks/velin-code-block-TSUKPY4C.js +123 -0
- package/dist/chunks/velin-code-block-Y6CM726Q.js +119 -0
- package/dist/chunks/velin-collapse-5XYBUIID.js +80 -0
- package/dist/chunks/velin-combobox-2KDTCQ7N.js +155 -0
- package/dist/chunks/velin-combobox-NXS4QB4R.js +155 -0
- package/dist/chunks/velin-combobox-UGA56HP3.js +155 -0
- package/dist/chunks/velin-command-CKDNO4BW.js +148 -0
- package/dist/chunks/velin-command-M7RNHUPR.js +136 -0
- package/dist/chunks/velin-command-ONKO2A3J.js +136 -0
- package/dist/chunks/velin-command-TMLSRGIU.js +136 -0
- package/dist/chunks/velin-copy-G2TZ5YBB.js +81 -0
- package/dist/chunks/velin-copy-NYDBOKXT.js +81 -0
- package/dist/chunks/velin-copy-T5KDTDXP.js +81 -0
- package/dist/chunks/velin-countdown-4ZVDGK4R.js +101 -0
- package/dist/chunks/velin-countdown-5XSTN3BH.js +101 -0
- package/dist/chunks/velin-countdown-7AIY66CU.js +101 -0
- package/dist/chunks/velin-counter-ISCTEAHI.js +118 -0
- package/dist/chunks/velin-counter-L5FYJF7A.js +121 -0
- package/dist/chunks/velin-dialog-D2GUHSCD.js +144 -0
- package/dist/chunks/velin-dialog-ELFOZIXZ.js +152 -0
- package/dist/chunks/velin-dialog-GTTZI564.js +147 -0
- package/dist/chunks/velin-dialog-IJLFDXAJ.js +144 -0
- package/dist/chunks/velin-dialog-TNS3WXMB.js +144 -0
- package/dist/chunks/velin-drawer-BE6TYN3H.js +130 -0
- package/dist/chunks/velin-drawer-DLL2GLT6.js +130 -0
- package/dist/chunks/velin-drawer-MJS6WCF7.js +130 -0
- package/dist/chunks/velin-dropdown-PLUIFA5M.js +172 -0
- package/dist/chunks/velin-email-N5B5ZYTE.js +90 -0
- package/dist/chunks/velin-email-NTM6DG3V.js +90 -0
- package/dist/chunks/velin-email-RBX6ZR4S.js +90 -0
- package/dist/chunks/velin-haptic-4QQTM3RK.js +50 -0
- package/dist/chunks/velin-icon-7M76DOPB.js +164 -0
- package/dist/chunks/velin-icon-KZO3IEHG.js +164 -0
- package/dist/chunks/velin-icon-WTFPG2DD.js +191 -0
- package/dist/chunks/velin-icon-ZTSKUOVN.js +193 -0
- package/dist/chunks/velin-lightbox-6E7CAATP.js +149 -0
- package/dist/chunks/velin-lightbox-I75U6JF4.js +140 -0
- package/dist/chunks/velin-lightbox-QOTB4PRL.js +140 -0
- package/dist/chunks/velin-lightbox-UCD6N7HF.js +140 -0
- package/dist/chunks/velin-live-dot-RJHX2DGY.js +74 -0
- package/dist/chunks/velin-live-dot-XHUZCIDZ.js +67 -0
- package/dist/chunks/velin-menubar-I426AED2.js +86 -0
- package/dist/chunks/velin-menubar-J66JXRWW.js +86 -0
- package/dist/chunks/velin-menubar-SFEXJE56.js +86 -0
- package/dist/chunks/velin-modal-2HOBXE6F.js +176 -0
- package/dist/chunks/velin-modal-5HYNNNUI.js +176 -0
- package/dist/chunks/velin-modal-AEOTZ67O.js +177 -0
- package/dist/chunks/velin-modal-GLI2XZZB.js +176 -0
- package/dist/chunks/velin-persist-DFPL3QP4.js +110 -0
- package/dist/chunks/velin-popover-EXINRIGJ.js +145 -0
- package/dist/chunks/velin-popover-HQW6Q2Y6.js +172 -0
- package/dist/chunks/velin-popover-OXX7MRZ6.js +145 -0
- package/dist/chunks/velin-popover-T72HK3DF.js +151 -0
- package/dist/chunks/velin-popover-YKCCROJG.js +145 -0
- package/dist/chunks/velin-progress-ring-E4YRLZHH.js +66 -0
- package/dist/chunks/velin-rating-6CDBI6DG.js +91 -0
- package/dist/chunks/velin-rating-N4DI2XNL.js +91 -0
- package/dist/chunks/velin-rating-XRQJV4LO.js +91 -0
- package/dist/chunks/velin-scroll-top-F2FCZNYD.js +58 -0
- package/dist/chunks/velin-scroll-top-OHYVVHHY.js +58 -0
- package/dist/chunks/velin-scrollspy-OKCT4FDV.js +50 -0
- package/dist/chunks/velin-search-2XRQFBCS.js +556 -0
- package/dist/chunks/velin-search-4YHJWYSS.js +556 -0
- package/dist/chunks/velin-search-7B4KJ6TX.js +557 -0
- package/dist/chunks/velin-search-LWHY23Q5.js +474 -0
- package/dist/chunks/velin-secure-field-6PV7RZDJ.js +95 -0
- package/dist/chunks/velin-secure-field-H7FSBUJW.js +95 -0
- package/dist/chunks/velin-secure-field-OFNAXCDP.js +95 -0
- package/dist/chunks/velin-segmented-control-EKL4E3BL.js +109 -0
- package/dist/chunks/velin-segmented-control-GYD5BIXQ.js +109 -0
- package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +109 -0
- package/dist/chunks/velin-sheet-3OGI4HD7.js +119 -0
- package/dist/chunks/velin-sheet-OUK6572T.js +119 -0
- package/dist/chunks/velin-sheet-R2Y67X6H.js +119 -0
- package/dist/chunks/velin-sparkline-GVEANJVW.js +184 -0
- package/dist/chunks/velin-sparkline-KDA3GQAN.js +162 -0
- package/dist/chunks/velin-sparkline-XVTFC6GE.js +181 -0
- package/dist/chunks/velin-stepper-2ZIHLKGM.js +141 -0
- package/dist/chunks/velin-stepper-7ECRUYHD.js +148 -0
- package/dist/chunks/velin-stepper-FYEUEWE6.js +141 -0
- package/dist/chunks/velin-stepper-X54WGHDG.js +141 -0
- package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +133 -0
- package/dist/chunks/velin-tabs-5UQ5ZVMV.js +138 -0
- package/dist/chunks/velin-theme-toggle-32J2CBNC.js +291 -0
- package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +285 -0
- package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +285 -0
- package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +291 -0
- package/dist/chunks/velin-toast-OMMOA2DK.js +109 -0
- package/dist/chunks/velin-toast-RCZ4CSUC.js +109 -0
- package/dist/chunks/velin-toast-RSF2IHT3.js +113 -0
- package/dist/chunks/velin-toast-WEUBTJG6.js +109 -0
- package/dist/chunks/velin-tooltip-664IOHZA.js +112 -0
- package/dist/chunks/velin-tooltip-BDHGRTQB.js +112 -0
- package/dist/chunks/velin-tooltip-HVUOKNVX.js +112 -0
- package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +103 -0
- package/dist/chunks/worker-client-R6DBYPFT.js +46 -0
- package/dist/llms.test.txt +40 -0
- package/dist/llms.txt +40 -0
- package/dist/search-index.json +1773 -0
- package/dist/search-index.test.json +1773 -0
- package/dist/themes/brutalist.min.css +1 -1
- package/dist/themes/midnight.min.css +1 -1
- package/dist/themes/pastel.min.css +1 -1
- package/dist/themes/retro.min.css +1 -1
- package/dist/themes/sunset.min.css +1 -1
- package/dist/velin-agent.json +684 -0
- package/dist/velin-agent.test.json +684 -0
- package/dist/velinstyle-components.iife.js +7715 -3515
- package/dist/velinstyle-components.js +7087 -2859
- package/dist/velinstyle-components.min.js +196 -109
- package/dist/velinstyle.css +604 -65
- package/dist/velinstyle.d.ts +54 -0
- package/dist/velinstyle.min.css +1 -1
- package/examples/search-index.schema.json +33 -0
- package/package.json +56 -10
- package/src/a11y/authentication.css +37 -0
- package/src/a11y/consistent-help.css +22 -0
- package/src/a11y/dragging-alternatives.css +30 -0
- package/src/a11y/focus-appearance.css +20 -0
- package/src/a11y/high-contrast-aaa.css +16 -26
- package/src/a11y/skip-link.css +3 -1
- package/src/a11y/sr-only.css +1 -1
- package/src/base/reset.css +0 -36
- package/src/base/wc-placeholder.css +102 -0
- package/src/components/attributes.css +42 -0
- package/src/components/highlight.css +182 -0
- package/src/components/input-group.css +1 -2
- package/src/components/nav.css +2 -3
- package/src/components/search.css +95 -0
- package/src/components/stepper.css +2 -4
- package/src/components/timeline.css +1 -2
- package/src/components/tooltip.css +2 -4
- package/src/layout/container.css +5 -5
- package/src/layout/grid.css +8 -8
- package/src/layout/patterns.css +5 -5
- package/src/themes/brutalist.css +2 -11
- package/src/themes/corporate.css +0 -9
- package/src/themes/earth.css +0 -9
- package/src/themes/forest.css +0 -9
- package/src/themes/midnight.css +1 -10
- package/src/themes/neon.css +0 -9
- package/src/themes/nordic.css +0 -9
- package/src/themes/ocean.css +0 -9
- package/src/themes/pastel.css +1 -10
- package/src/themes/retro.css +2 -11
- package/src/themes/sharp.css +0 -7
- package/src/themes/soft.css +0 -7
- package/src/themes/sunset.css +1 -10
- package/src/tokens/color.css +45 -46
- package/src/tokens/fonts.css +10 -0
- package/src/tokens/typography.css +4 -5
- package/src/utilities/animation.css +2 -2
- package/src/utilities/display.css +3 -3
- package/src/utilities/divide.css +2 -6
- package/src/utilities/responsive.css +4 -4
- package/src/utilities/safe-area.css +1 -1
- package/src/utilities/scroll-animation.css +34 -0
- package/src/utilities/spacing.css +17 -8
- package/src/utilities/text.css +4 -1
- 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',
|
|
51
|
-
'utilities/filter.css', 'utilities/
|
|
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.
|
|
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
|
|
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
|
+
}
|