vibe-design-system 1.8.5 → 1.9.2
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/bin/init.js +105 -9
- package/package.json +1 -1
- package/vds-core-template/story-generator.mjs +146 -27
package/bin/init.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* VDS installer: npx vibe-design-system init
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Single command that:
|
|
6
|
+
* 1. Copies vds-core files (scan.mjs, story-generator.mjs, dashboard-server.mjs)
|
|
7
|
+
* 2. Installs Storybook if not present (npx storybook@latest init --yes)
|
|
8
|
+
* 3. Creates/updates .storybook/preview with index.css import and dark decorator
|
|
9
|
+
* 4. Runs node vds-core/scan.mjs
|
|
10
|
+
* 5. Runs node vds-core/story-generator.mjs
|
|
11
|
+
* 6. Adds all scripts to package.json
|
|
8
12
|
*/
|
|
9
13
|
import fs from "fs";
|
|
10
14
|
import path from "path";
|
|
@@ -24,6 +28,66 @@ function getProjectRoot() {
|
|
|
24
28
|
return cwd;
|
|
25
29
|
}
|
|
26
30
|
|
|
31
|
+
function isStorybookInstalled(projectRoot) {
|
|
32
|
+
const storybookDir = path.join(projectRoot, ".storybook");
|
|
33
|
+
if (fs.existsSync(storybookDir)) return true;
|
|
34
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
35
|
+
try {
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
37
|
+
const dev = pkg.devDependencies || {};
|
|
38
|
+
if (dev["@storybook/react-vite"] || dev["storybook"]) return true;
|
|
39
|
+
} catch (_) {}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function installStorybook(projectRoot) {
|
|
44
|
+
console.log("📚 Storybook kuruluyor...");
|
|
45
|
+
const r = spawnSync("npx", ["storybook@latest", "init", "--yes"], {
|
|
46
|
+
cwd: projectRoot,
|
|
47
|
+
stdio: "inherit",
|
|
48
|
+
shell: true,
|
|
49
|
+
});
|
|
50
|
+
if (r.status !== 0) {
|
|
51
|
+
console.warn("⚠️ Storybook init tamamlanamadı; manuel: npx storybook@latest init");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const PREVIEW_CONTENT = `import type { Preview } from "@storybook/react-vite";
|
|
56
|
+
import React from "react";
|
|
57
|
+
import "../src/index.css";
|
|
58
|
+
|
|
59
|
+
const preview: Preview = {
|
|
60
|
+
parameters: {
|
|
61
|
+
controls: {
|
|
62
|
+
matchers: {
|
|
63
|
+
color: /(background|color)$/i,
|
|
64
|
+
date: /Date$/i,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
decorators: [
|
|
69
|
+
(Story) => (
|
|
70
|
+
<div className="dark" style={{ minHeight: "100vh", padding: "1rem" }}>
|
|
71
|
+
<Story />
|
|
72
|
+
</div>
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default preview;
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
function ensureStorybookPreview(projectRoot) {
|
|
81
|
+
const storybookDir = path.join(projectRoot, ".storybook");
|
|
82
|
+
if (!fs.existsSync(storybookDir)) fs.mkdirSync(storybookDir, { recursive: true });
|
|
83
|
+
|
|
84
|
+
const previewTsx = path.join(storybookDir, "preview.tsx");
|
|
85
|
+
const previewTs = path.join(storybookDir, "preview.ts");
|
|
86
|
+
if (fs.existsSync(previewTs)) try { fs.unlinkSync(previewTs); } catch (_) {}
|
|
87
|
+
fs.writeFileSync(previewTsx, PREVIEW_CONTENT, "utf-8");
|
|
88
|
+
console.log("📝 .storybook/preview.tsx güncellendi (index.css + dark decorator).");
|
|
89
|
+
}
|
|
90
|
+
|
|
27
91
|
function addScripts(projectRoot) {
|
|
28
92
|
const pkgPath = path.join(projectRoot, "package.json");
|
|
29
93
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
@@ -32,6 +96,8 @@ function addScripts(projectRoot) {
|
|
|
32
96
|
if (!scripts["vds:watch"]) scripts["vds:watch"] = "node vds-core/scan.mjs --watch";
|
|
33
97
|
if (!scripts["vds:dashboard"]) scripts["vds:dashboard"] = "node vds-core/dashboard-server.mjs";
|
|
34
98
|
if (!scripts["vds:stories"]) scripts["vds:stories"] = "node vds-core/story-generator.mjs";
|
|
99
|
+
if (!scripts.storybook) scripts.storybook = "storybook dev -p 6006";
|
|
100
|
+
if (!scripts["build-storybook"]) scripts["build-storybook"] = "storybook build";
|
|
35
101
|
pkg.scripts = scripts;
|
|
36
102
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), "utf-8");
|
|
37
103
|
}
|
|
@@ -41,7 +107,7 @@ function addVdsDependency(projectRoot) {
|
|
|
41
107
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
42
108
|
const dev = pkg.devDependencies || {};
|
|
43
109
|
if (!dev["vibe-design-system"]) {
|
|
44
|
-
dev["vibe-design-system"] = "^1.
|
|
110
|
+
dev["vibe-design-system"] = "^1.9.0";
|
|
45
111
|
pkg.devDependencies = dev;
|
|
46
112
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), "utf-8");
|
|
47
113
|
const r = spawnSync("npm", ["install"], { cwd: projectRoot, stdio: "inherit", shell: true });
|
|
@@ -64,9 +130,6 @@ function ensureVdsCore(projectRoot) {
|
|
|
64
130
|
const serverSrc = path.join(TEMPLATE_DIR, "dashboard-server.mjs");
|
|
65
131
|
if (fs.existsSync(serverSrc)) {
|
|
66
132
|
fs.copyFileSync(serverSrc, path.join(vdsCoreDest, "dashboard-server.mjs"));
|
|
67
|
-
} else {
|
|
68
|
-
console.error("vds-core-template/dashboard-server.mjs bulunamadı.");
|
|
69
|
-
process.exit(1);
|
|
70
133
|
}
|
|
71
134
|
|
|
72
135
|
const storyGenSrc = path.join(TEMPLATE_DIR, "story-generator.mjs");
|
|
@@ -78,6 +141,7 @@ function ensureVdsCore(projectRoot) {
|
|
|
78
141
|
function runScan(projectRoot) {
|
|
79
142
|
const scanPath = path.join(projectRoot, "vds-core", "scan.mjs");
|
|
80
143
|
if (!fs.existsSync(scanPath)) return;
|
|
144
|
+
console.log("🔍 VDS taraması çalıştırılıyor...");
|
|
81
145
|
const r = spawnSync("node", [scanPath], {
|
|
82
146
|
cwd: projectRoot,
|
|
83
147
|
stdio: "inherit",
|
|
@@ -86,6 +150,18 @@ function runScan(projectRoot) {
|
|
|
86
150
|
if (r.status !== 0) process.exitCode = r.status ?? 1;
|
|
87
151
|
}
|
|
88
152
|
|
|
153
|
+
function runStoryGenerator(projectRoot) {
|
|
154
|
+
const genPath = path.join(projectRoot, "vds-core", "story-generator.mjs");
|
|
155
|
+
if (!fs.existsSync(genPath)) return;
|
|
156
|
+
console.log("📖 Story dosyaları oluşturuluyor...");
|
|
157
|
+
const r = spawnSync("node", [genPath], {
|
|
158
|
+
cwd: projectRoot,
|
|
159
|
+
stdio: "inherit",
|
|
160
|
+
shell: false,
|
|
161
|
+
});
|
|
162
|
+
if (r.status !== 0) process.exitCode = r.status ?? 1;
|
|
163
|
+
}
|
|
164
|
+
|
|
89
165
|
console.log("🎨 VDS kuruluyor...");
|
|
90
166
|
|
|
91
167
|
const projectRoot = getProjectRoot();
|
|
@@ -96,9 +172,29 @@ if (!fs.existsSync(pkgPath)) {
|
|
|
96
172
|
process.exit(1);
|
|
97
173
|
}
|
|
98
174
|
|
|
175
|
+
// 1. Copy vds-core files
|
|
99
176
|
ensureVdsCore(projectRoot);
|
|
177
|
+
|
|
178
|
+
// 2. Install Storybook if not present
|
|
179
|
+
if (!isStorybookInstalled(projectRoot)) {
|
|
180
|
+
installStorybook(projectRoot);
|
|
181
|
+
} else {
|
|
182
|
+
console.log("📚 Storybook zaten mevcut.");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 3. Create/update .storybook/preview with index.css + dark decorator
|
|
186
|
+
ensureStorybookPreview(projectRoot);
|
|
187
|
+
|
|
188
|
+
// 6. Add all scripts to package.json (before scan so scripts are there)
|
|
100
189
|
addScripts(projectRoot);
|
|
101
190
|
addVdsDependency(projectRoot);
|
|
191
|
+
|
|
192
|
+
// 4. Run scan
|
|
102
193
|
runScan(projectRoot);
|
|
103
194
|
|
|
104
|
-
|
|
195
|
+
// 5. Run story generator
|
|
196
|
+
runStoryGenerator(projectRoot);
|
|
197
|
+
|
|
198
|
+
console.log("✅ Kurulum tamamlandı.");
|
|
199
|
+
console.log(" Storybook: npm run storybook");
|
|
200
|
+
console.log(" Dashboard: npm run vds:dashboard");
|
package/package.json
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* VDS Story generator
|
|
4
4
|
*
|
|
5
|
-
* Reads vds-output.json and generates
|
|
6
|
-
* under src/stories for each component
|
|
5
|
+
* Reads vds-output.json and generates:
|
|
6
|
+
* - Storybook .stories.tsx files under src/stories for each component
|
|
7
|
+
* - Foundations MDX: Colors, Typography, Brand under src/stories/foundations/
|
|
7
8
|
*
|
|
8
9
|
* Usage:
|
|
9
10
|
* node vds-core/story-generator.mjs # generate for all components
|
|
@@ -19,6 +20,12 @@ const VDS_OUTPUT = path.join(PROJECT_ROOT, "vds-output.json");
|
|
|
19
20
|
const SRC_DIR = path.join(PROJECT_ROOT, "src");
|
|
20
21
|
const STORIES_DIR = path.join(SRC_DIR, "stories");
|
|
21
22
|
|
|
23
|
+
// Top of every story file for CSS variables
|
|
24
|
+
const STORY_CSS_HEADER = `// @ts-ignore
|
|
25
|
+
import '../../index.css'
|
|
26
|
+
|
|
27
|
+
`;
|
|
28
|
+
|
|
22
29
|
// Components we don't want to auto-generate stories for (project-specific dashboards, heavy UIs, etc.)
|
|
23
30
|
const SKIP_LIST = [
|
|
24
31
|
"AnalysisDashboard",
|
|
@@ -37,28 +44,41 @@ const SKIP_LIST = [
|
|
|
37
44
|
"TestComponent",
|
|
38
45
|
];
|
|
39
46
|
|
|
40
|
-
// Components that need a router context
|
|
41
|
-
const ROUTER_DECORATOR_LIST = ["Breadcrumb", "NavigationMenu", "Sidebar", "Menubar"];
|
|
42
|
-
|
|
43
47
|
function ensureDir(dir) {
|
|
44
48
|
if (!fs.existsSync(dir)) {
|
|
45
49
|
fs.mkdirSync(dir, { recursive: true });
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
/** Detect if component uses router (useLocation, useNavigate, or Link from react-router-dom). */
|
|
54
|
+
function needsRouter(source) {
|
|
55
|
+
if (!source || typeof source !== "string") return false;
|
|
56
|
+
if (/\buseLocation\b|\buseNavigate\b/.test(source)) return true;
|
|
57
|
+
if (/from\s+['"]react-router-dom['"]/.test(source) && /\bLink\b/.test(source)) return true;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** If component has <img and accepts children prop, we should omit children from story args (void element). */
|
|
62
|
+
function componentHasImgAndChildren(source) {
|
|
63
|
+
if (!source || typeof source !== "string") return false;
|
|
64
|
+
const hasImg = /return\s+<img|<\s*img\s+/.test(source);
|
|
65
|
+
if (!hasImg) return false;
|
|
66
|
+
return /\bchildren\b/.test(source);
|
|
67
|
+
}
|
|
68
|
+
|
|
49
69
|
function toSafeComponentName(name, file) {
|
|
50
|
-
if (name
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
if (!name || typeof name !== "string") {
|
|
71
|
+
const base = (file || "").replace(/\.[^.]+$/, "");
|
|
72
|
+
const parts = base.split(/[\\/]/g);
|
|
73
|
+
const last = parts[parts.length - 1] || "Component";
|
|
74
|
+
return last.charAt(0).toUpperCase() + last.slice(1);
|
|
75
|
+
}
|
|
76
|
+
return name
|
|
77
|
+
.replace(/[^A-Za-z0-9]+/g, " ")
|
|
78
|
+
.trim()
|
|
79
|
+
.replace(/\s+([a-z])/g, (_, c) => c.toUpperCase())
|
|
80
|
+
.replace(/^\w/, (c) => c.toUpperCase())
|
|
81
|
+
.replace(/\s+/g, "");
|
|
62
82
|
}
|
|
63
83
|
|
|
64
84
|
function parseUnionLiterals(type) {
|
|
@@ -308,6 +328,7 @@ function buildStoryFileContent(comp) {
|
|
|
308
328
|
// ignore
|
|
309
329
|
}
|
|
310
330
|
const exportStyle = detectExportStyle(source, componentName);
|
|
331
|
+
const omitChildren = componentHasImgAndChildren(source);
|
|
311
332
|
|
|
312
333
|
const lines = [];
|
|
313
334
|
lines.push(`import type { Meta, StoryObj } from "@storybook/react";`);
|
|
@@ -347,7 +368,8 @@ function buildStoryFileContent(comp) {
|
|
|
347
368
|
`import { CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card";`,
|
|
348
369
|
);
|
|
349
370
|
}
|
|
350
|
-
|
|
371
|
+
const useRouterDecorator = needsRouter(source);
|
|
372
|
+
if (useRouterDecorator) {
|
|
351
373
|
lines.push(`import { MemoryRouter } from "react-router-dom";`);
|
|
352
374
|
}
|
|
353
375
|
|
|
@@ -356,7 +378,7 @@ function buildStoryFileContent(comp) {
|
|
|
356
378
|
lines.push(` title: ${JSON.stringify(title)},`);
|
|
357
379
|
lines.push(` component: ComponentRef,`);
|
|
358
380
|
lines.push(` tags: ["autodocs"],`);
|
|
359
|
-
if (
|
|
381
|
+
if (useRouterDecorator) {
|
|
360
382
|
lines.push(` decorators: [(Story) => (`);
|
|
361
383
|
lines.push(` <MemoryRouter>`);
|
|
362
384
|
lines.push(` <Story />`);
|
|
@@ -373,14 +395,14 @@ function buildStoryFileContent(comp) {
|
|
|
373
395
|
const specialStories = buildSpecialStories(componentName, variants);
|
|
374
396
|
if (specialStories) {
|
|
375
397
|
lines.push(specialStories);
|
|
376
|
-
return lines.join("\n");
|
|
398
|
+
return STORY_CSS_HEADER + lines.join("\n");
|
|
377
399
|
}
|
|
378
400
|
|
|
379
|
-
// Generic variant-based stories
|
|
401
|
+
// Generic variant-based stories (omit children for img/void components)
|
|
380
402
|
if (!variants.length) {
|
|
381
403
|
lines.push(`export const Default: Story = {`);
|
|
382
404
|
lines.push(` args: {`);
|
|
383
|
-
lines.push(` children: "${componentName}",`);
|
|
405
|
+
if (!omitChildren) lines.push(` children: "${componentName}",`);
|
|
384
406
|
lines.push(` },`);
|
|
385
407
|
lines.push(`};`);
|
|
386
408
|
} else {
|
|
@@ -388,7 +410,7 @@ function buildStoryFileContent(comp) {
|
|
|
388
410
|
lines.push(`export const ${capitalize(defaultVariant)}: Story = {`);
|
|
389
411
|
lines.push(` args: {`);
|
|
390
412
|
lines.push(` variant: "${defaultVariant}",`);
|
|
391
|
-
lines.push(` children: "${componentName}",`);
|
|
413
|
+
if (!omitChildren) lines.push(` children: "${componentName}",`);
|
|
392
414
|
lines.push(` },`);
|
|
393
415
|
lines.push(`};`);
|
|
394
416
|
lines.push("");
|
|
@@ -397,14 +419,107 @@ function buildStoryFileContent(comp) {
|
|
|
397
419
|
lines.push(`export const ${storyName}: Story = {`);
|
|
398
420
|
lines.push(` args: {`);
|
|
399
421
|
lines.push(` variant: "${v}",`);
|
|
400
|
-
lines.push(` children: "${storyName}",`);
|
|
422
|
+
if (!omitChildren) lines.push(` children: "${storyName}",`);
|
|
401
423
|
lines.push(` },`);
|
|
402
424
|
lines.push(`};`);
|
|
403
425
|
lines.push("");
|
|
404
426
|
}
|
|
405
427
|
}
|
|
406
428
|
|
|
407
|
-
return lines.join("\n");
|
|
429
|
+
return STORY_CSS_HEADER + lines.join("\n");
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** Build color entries from foundations.colors (skip _dark; flatten to { name, hex }). */
|
|
433
|
+
function getColorEntries(colors) {
|
|
434
|
+
if (!colors || typeof colors !== "object") return [];
|
|
435
|
+
const entries = [];
|
|
436
|
+
for (const [name, v] of Object.entries(colors)) {
|
|
437
|
+
if (name === "_dark") continue;
|
|
438
|
+
const hex = v && (v.hex ?? (typeof v.value === "string" && v.value.startsWith("#") ? v.value : null));
|
|
439
|
+
const value = v && v.value;
|
|
440
|
+
if (hex) entries.push({ name, hex });
|
|
441
|
+
else if (value) entries.push({ name, hex: value });
|
|
442
|
+
}
|
|
443
|
+
return entries;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function writeFoundationsMdx(foundations) {
|
|
447
|
+
const foundationsDir = path.join(STORIES_DIR, "foundations");
|
|
448
|
+
ensureDir(foundationsDir);
|
|
449
|
+
|
|
450
|
+
const colors = foundations?.colors;
|
|
451
|
+
const colorEntries = getColorEntries(colors);
|
|
452
|
+
if (colorEntries.length > 0) {
|
|
453
|
+
const colorLines = [
|
|
454
|
+
"import { Meta } from '@storybook/blocks';",
|
|
455
|
+
"",
|
|
456
|
+
"<Meta title=\"Foundations/Colors\" />",
|
|
457
|
+
"",
|
|
458
|
+
"# Colors",
|
|
459
|
+
"",
|
|
460
|
+
"<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))', gap: '1rem' }}>",
|
|
461
|
+
...colorEntries.map(
|
|
462
|
+
(e) =>
|
|
463
|
+
` <div key="${e.name}"><div style={{ backgroundColor: '${e.hex.replace(/'/g, "\\'")}', height: 80, borderRadius: 8, border: '1px solid #333' }} /><p style={{ marginTop: 8, fontSize: 12 }}>${e.name}</p><code style={{ fontSize: 11 }}>${e.hex}</code></div>`,
|
|
464
|
+
),
|
|
465
|
+
"</div>",
|
|
466
|
+
];
|
|
467
|
+
fs.writeFileSync(path.join(foundationsDir, "Colors.stories.mdx"), colorLines.join("\n"), "utf-8");
|
|
468
|
+
console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "Colors.stories.mdx")));
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const typo = foundations?.typography;
|
|
472
|
+
if (typo && typeof typo === "object" && Object.keys(typo).length > 0) {
|
|
473
|
+
const bodyVal = typo.body || typo.bodyFontFamily || "";
|
|
474
|
+
const monoVal = typo.mono || typo.tailwindMono;
|
|
475
|
+
const monoStr = Array.isArray(monoVal) ? monoVal.join(", ") : String(monoVal || "");
|
|
476
|
+
const typoContent = [
|
|
477
|
+
"import { Meta } from '@storybook/blocks';",
|
|
478
|
+
"",
|
|
479
|
+
"<Meta title=\"Foundations/Typography\" />",
|
|
480
|
+
"",
|
|
481
|
+
"# Typography",
|
|
482
|
+
"",
|
|
483
|
+
"## Font family & scale",
|
|
484
|
+
"",
|
|
485
|
+
"| Token | Value |",
|
|
486
|
+
"| --- | --- |",
|
|
487
|
+
...Object.entries(typo).map(([k, v]) => {
|
|
488
|
+
const val = Array.isArray(v) ? v.join(", ") : String(v);
|
|
489
|
+
return `| ${k} | ${val} |`;
|
|
490
|
+
}),
|
|
491
|
+
"",
|
|
492
|
+
"## Preview",
|
|
493
|
+
"",
|
|
494
|
+
`<p style={{ fontFamily: ${JSON.stringify(bodyVal)}, fontSize: 16 }}>The quick brown fox jumps over the lazy dog.</p>`,
|
|
495
|
+
`<p style={{ fontFamily: ${JSON.stringify(monoStr)}, fontSize: 14 }}>Code: 0123456789</p>`,
|
|
496
|
+
];
|
|
497
|
+
fs.writeFileSync(path.join(foundationsDir, "Typography.stories.mdx"), typoContent.join("\n"), "utf-8");
|
|
498
|
+
console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "Typography.stories.mdx")));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const brandAssets = foundations?.brand?.assets;
|
|
502
|
+
if (Array.isArray(brandAssets) && brandAssets.length > 0) {
|
|
503
|
+
const assetRows = brandAssets.map(
|
|
504
|
+
(a) =>
|
|
505
|
+
` <tr key="${(a.path || a.name || "").replace(/"/g, '\\"')}"><td>${a.type || "asset"}</td><td><code>${a.path || a.name || ""}</code></td><td>${a.name || ""}</td></tr>`,
|
|
506
|
+
);
|
|
507
|
+
const brandContent = [
|
|
508
|
+
"import { Meta } from '@storybook/blocks';",
|
|
509
|
+
"",
|
|
510
|
+
"<Meta title=\"Foundations/Brand\" />",
|
|
511
|
+
"",
|
|
512
|
+
"# Brand",
|
|
513
|
+
"",
|
|
514
|
+
"Logo and favicon paths from the project.",
|
|
515
|
+
"",
|
|
516
|
+
"<table><thead><tr><th>Type</th><th>Path</th><th>Name</th></tr></thead><tbody>",
|
|
517
|
+
...assetRows,
|
|
518
|
+
"</tbody></table>",
|
|
519
|
+
];
|
|
520
|
+
fs.writeFileSync(path.join(foundationsDir, "Brand.stories.mdx"), brandContent.join("\n"), "utf-8");
|
|
521
|
+
console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "Brand.stories.mdx")));
|
|
522
|
+
}
|
|
408
523
|
}
|
|
409
524
|
|
|
410
525
|
function main() {
|
|
@@ -415,14 +530,19 @@ function main() {
|
|
|
415
530
|
const raw = fs.readFileSync(VDS_OUTPUT, "utf-8");
|
|
416
531
|
const data = JSON.parse(raw);
|
|
417
532
|
const components = Array.isArray(data.components) ? data.components : [];
|
|
533
|
+
const foundations = data.foundations || null;
|
|
418
534
|
|
|
419
535
|
const onlyName = process.argv[2] || null;
|
|
420
536
|
|
|
421
537
|
ensureDir(STORIES_DIR);
|
|
422
|
-
|
|
538
|
+
ensureDir(path.join(STORIES_DIR, "foundations"));
|
|
539
|
+
writeFoundationsMdx(foundations);
|
|
540
|
+
|
|
541
|
+
// Clear existing .stories.* files (except foundations/*.mdx) so only VDS-generated stories remain
|
|
423
542
|
try {
|
|
424
543
|
const existing = fs.readdirSync(STORIES_DIR);
|
|
425
544
|
for (const name of existing) {
|
|
545
|
+
if (name === "foundations") continue;
|
|
426
546
|
if (
|
|
427
547
|
name.endsWith(".stories.tsx") ||
|
|
428
548
|
name.endsWith(".stories.ts") ||
|
|
@@ -450,4 +570,3 @@ function main() {
|
|
|
450
570
|
}
|
|
451
571
|
|
|
452
572
|
main();
|
|
453
|
-
|