vibe-design-system 2.0.0 → 2.1.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/bin/init.js +35 -10
- package/package.json +1 -1
- package/vds-core-template/scan.mjs +121 -5
- package/vds-core-template/story-generator.mjs +63 -0
- package/vds-core-template/watch.mjs +36 -0
package/bin/init.js
CHANGED
|
@@ -54,16 +54,41 @@ Geliştirme kuralları:
|
|
|
54
54
|
`;
|
|
55
55
|
|
|
56
56
|
const WATCH_MJS = `#!/usr/bin/env node
|
|
57
|
-
import {
|
|
58
|
-
import
|
|
59
|
-
import {
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
import { watch } from 'fs';
|
|
58
|
+
import { execSync } from 'child_process';
|
|
59
|
+
import { resolve } from 'path';
|
|
60
|
+
|
|
61
|
+
const ROOT = resolve(process.cwd());
|
|
62
|
+
const SRC = resolve(ROOT, 'src');
|
|
63
|
+
let timeout = null;
|
|
64
|
+
|
|
65
|
+
function run() {
|
|
66
|
+
const ts = new Date().toLocaleTimeString();
|
|
67
|
+
console.log(\`\\n[VDS \${ts}] Değişiklik algılandı, taranıyor...\`);
|
|
68
|
+
try {
|
|
69
|
+
execSync('node vds-core/scan.mjs', { stdio: 'inherit', cwd: ROOT });
|
|
70
|
+
execSync('node vds-core/story-generator.mjs', { stdio: 'inherit', cwd: ROOT });
|
|
71
|
+
console.log(\`[VDS \${ts}] ✅ Design system güncellendi.\`);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.error(\`[VDS \${ts}] ❌ Hata:\`, e.message);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function onFileChange(eventType, filename) {
|
|
78
|
+
if (!filename) return;
|
|
79
|
+
if (filename.includes('stories/')) return;
|
|
80
|
+
if (filename.includes('vds-output')) return;
|
|
81
|
+
if (!filename.endsWith('.tsx') && !filename.endsWith('.ts') &&
|
|
82
|
+
!filename.endsWith('.css') && !filename.endsWith('.js')) return;
|
|
83
|
+
console.log(\`[VDS] Değişiklik: \${filename}\`);
|
|
84
|
+
clearTimeout(timeout);
|
|
85
|
+
timeout = setTimeout(run, 2000);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
run();
|
|
89
|
+
console.log('[VDS] 👀 src/ klasörü izleniyor...');
|
|
90
|
+
console.log('[VDS] Durdurmak için Ctrl+C\\n');
|
|
91
|
+
watch(SRC, { recursive: true }, onFileChange);
|
|
67
92
|
`;
|
|
68
93
|
|
|
69
94
|
const STORYBOOK_EXAMPLE_FILES = [
|
package/package.json
CHANGED
|
@@ -92,6 +92,106 @@ function readPreviousOutput() {
|
|
|
92
92
|
return null;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
function readPreviousOutputFull() {
|
|
96
|
+
try {
|
|
97
|
+
if (fs.existsSync(OUTPUT_FILE)) {
|
|
98
|
+
const raw = fs.readFileSync(OUTPUT_FILE, "utf-8");
|
|
99
|
+
return JSON.parse(raw);
|
|
100
|
+
}
|
|
101
|
+
} catch (_) {}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const CHANGELOG_MAX_ENTRIES = 20;
|
|
106
|
+
|
|
107
|
+
function getColorHex(val) {
|
|
108
|
+
if (val == null) return null;
|
|
109
|
+
if (typeof val === "string") return val;
|
|
110
|
+
if (typeof val === "object" && (val.hex || val.value)) return val.hex || val.value;
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function compareColors(prevColors, newColors) {
|
|
115
|
+
const changes = [];
|
|
116
|
+
if (!prevColors && !newColors) return changes;
|
|
117
|
+
const prev = prevColors || {};
|
|
118
|
+
const next = newColors || {};
|
|
119
|
+
const allKeys = new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
120
|
+
for (const key of allKeys) {
|
|
121
|
+
if (key === "_dark") continue;
|
|
122
|
+
const fromHex = getColorHex(prev[key]);
|
|
123
|
+
const toHex = getColorHex(next[key]);
|
|
124
|
+
if (toHex == null) {
|
|
125
|
+
if (fromHex != null) changes.push({ type: "color_removed", name: key });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (fromHex == null) {
|
|
129
|
+
changes.push({ type: "color_added", name: key, to: toHex });
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (fromHex !== toHex) {
|
|
133
|
+
changes.push({ type: "color_changed", name: key, from: fromHex, to: toHex });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (next._dark && typeof next._dark === "object") {
|
|
137
|
+
const prevDark = prev._dark || {};
|
|
138
|
+
for (const key of Object.keys(next._dark)) {
|
|
139
|
+
const fromHex = getColorHex(prevDark[key]);
|
|
140
|
+
const toHex = getColorHex(next._dark[key]);
|
|
141
|
+
if (fromHex != null && toHex != null && fromHex !== toHex) {
|
|
142
|
+
changes.push({ type: "color_changed", name: `_dark.${key}`, from: fromHex, to: toHex });
|
|
143
|
+
} else if (fromHex == null && toHex != null) {
|
|
144
|
+
changes.push({ type: "color_added", name: `_dark.${key}`, to: toHex });
|
|
145
|
+
} else if (fromHex != null && toHex == null) {
|
|
146
|
+
changes.push({ type: "color_removed", name: `_dark.${key}` });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return changes;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function compareTypography(prevTypo, newTypo) {
|
|
154
|
+
const changes = [];
|
|
155
|
+
if (!prevTypo && !newTypo) return changes;
|
|
156
|
+
const prev = prevTypo || {};
|
|
157
|
+
const next = newTypo || {};
|
|
158
|
+
const allKeys = new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
159
|
+
for (const key of allKeys) {
|
|
160
|
+
const fromVal = prev[key] != null ? String(prev[key]) : null;
|
|
161
|
+
const toVal = next[key] != null ? String(next[key]) : null;
|
|
162
|
+
if (fromVal === toVal) continue;
|
|
163
|
+
if (toVal == null) continue;
|
|
164
|
+
changes.push({
|
|
165
|
+
type: "typography_changed",
|
|
166
|
+
key,
|
|
167
|
+
from: fromVal || "(none)",
|
|
168
|
+
to: toVal,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return changes;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function buildChangelogChanges(prevOutput, newOutput, added, removed) {
|
|
175
|
+
const changes = [];
|
|
176
|
+
const prevFoundations = prevOutput?.foundations;
|
|
177
|
+
const newFoundations = newOutput?.foundations;
|
|
178
|
+
|
|
179
|
+
const colorChanges = compareColors(prevFoundations?.colors, newFoundations?.colors);
|
|
180
|
+
changes.push(...colorChanges);
|
|
181
|
+
|
|
182
|
+
const typoChanges = compareTypography(prevFoundations?.typography, newFoundations?.typography);
|
|
183
|
+
changes.push(...typoChanges);
|
|
184
|
+
|
|
185
|
+
for (const a of added) {
|
|
186
|
+
changes.push({ type: "component_added", name: a.name });
|
|
187
|
+
}
|
|
188
|
+
for (const r of removed) {
|
|
189
|
+
changes.push({ type: "component_removed", name: r.name });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return changes;
|
|
193
|
+
}
|
|
194
|
+
|
|
95
195
|
function readLastVersion() {
|
|
96
196
|
try {
|
|
97
197
|
if (fs.existsSync(HISTORY_FILE)) {
|
|
@@ -760,21 +860,37 @@ function scan() {
|
|
|
760
860
|
componentSuggestions,
|
|
761
861
|
};
|
|
762
862
|
|
|
763
|
-
const
|
|
863
|
+
const prevOutput = readPreviousOutputFull();
|
|
864
|
+
const prevComponents = prevOutput?.components ?? readPreviousOutput();
|
|
764
865
|
const { added, removed, modified } = compareComponents(prevComponents, results);
|
|
765
866
|
const hasChanges = added.length > 0 || removed.length > 0 || modified.length > 0;
|
|
766
867
|
|
|
868
|
+
const prevVersion = prevOutput?.version || readLastVersion() || "1.0.0";
|
|
869
|
+
const changelogChanges = buildChangelogChanges(prevOutput, output, added, removed);
|
|
870
|
+
const prevChangelog = Array.isArray(prevOutput?.changelog) ? prevOutput.changelog : [];
|
|
871
|
+
if (changelogChanges.length > 0) {
|
|
872
|
+
const nextVersion = incPatch(prevVersion);
|
|
873
|
+
const changelogEntry = {
|
|
874
|
+
version: nextVersion,
|
|
875
|
+
date: new Date().toISOString(),
|
|
876
|
+
changes: changelogChanges,
|
|
877
|
+
};
|
|
878
|
+
output.changelog = prevChangelog.concat(changelogEntry).slice(-CHANGELOG_MAX_ENTRIES);
|
|
879
|
+
output.version = nextVersion;
|
|
880
|
+
} else {
|
|
881
|
+
output.changelog = prevChangelog;
|
|
882
|
+
output.version = prevVersion;
|
|
883
|
+
}
|
|
884
|
+
|
|
767
885
|
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(output, null, 2), "utf-8");
|
|
768
886
|
const publicDir = path.join(PROJECT_ROOT, "public");
|
|
769
887
|
if (!fs.existsSync(publicDir)) fs.mkdirSync(publicDir, { recursive: true });
|
|
770
888
|
fs.writeFileSync(PUBLIC_MANIFEST, JSON.stringify(output, null, 2), "utf-8");
|
|
771
889
|
|
|
772
890
|
if (hasChanges) {
|
|
773
|
-
const lastVersion = readLastVersion();
|
|
774
|
-
const nextVersion = incPatch(lastVersion);
|
|
775
891
|
const changes = [...added, ...removed, ...modified];
|
|
776
892
|
const historyEntry = {
|
|
777
|
-
version:
|
|
893
|
+
version: output.version,
|
|
778
894
|
timestamp: new Date().toISOString(),
|
|
779
895
|
branch: getGitBranch(),
|
|
780
896
|
engineer: getGitEngineer(),
|
|
@@ -784,7 +900,7 @@ function scan() {
|
|
|
784
900
|
entries.push(historyEntry);
|
|
785
901
|
fs.writeFileSync(HISTORY_FILE, JSON.stringify(entries, null, 2), "utf-8");
|
|
786
902
|
console.log(
|
|
787
|
-
`[VDS] v${
|
|
903
|
+
`[VDS] v${output.version}: ${added.length} added, ${removed.length} removed, ${modified.length} modified`
|
|
788
904
|
);
|
|
789
905
|
console.log(cliT("scanComplete", results.length));
|
|
790
906
|
}
|
|
@@ -813,6 +813,65 @@ function writeComponentSuggestionsStory(componentSuggestions) {
|
|
|
813
813
|
console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "ComponentSuggestions.stories.tsx")));
|
|
814
814
|
}
|
|
815
815
|
|
|
816
|
+
function writeChangelogStory(changelog) {
|
|
817
|
+
if (!Array.isArray(changelog) || changelog.length === 0) return;
|
|
818
|
+
const foundationsDir = path.join(STORIES_DIR, "foundations");
|
|
819
|
+
ensureDir(foundationsDir);
|
|
820
|
+
const entries = changelog.map((e) => ({
|
|
821
|
+
version: e.version,
|
|
822
|
+
date: e.date,
|
|
823
|
+
changes: e.changes || [],
|
|
824
|
+
}));
|
|
825
|
+
const content =
|
|
826
|
+
[
|
|
827
|
+
"import type { Meta, StoryObj } from \"@storybook/react\";",
|
|
828
|
+
"",
|
|
829
|
+
"const meta = { title: \"Foundations/Changelog\" } satisfies Meta;",
|
|
830
|
+
"export default meta;",
|
|
831
|
+
"type Story = StoryObj;",
|
|
832
|
+
"",
|
|
833
|
+
`const changelog = ${JSON.stringify(entries)};`,
|
|
834
|
+
"",
|
|
835
|
+
"function ChangeItem({ c }) {",
|
|
836
|
+
" if (c.type === \"color_changed\")",
|
|
837
|
+
" return (",
|
|
838
|
+
" <div style={{ marginBottom: 8 }}>",
|
|
839
|
+
" <strong>{c.name}</strong>: <span style={{ color: \"#888\" }}>{c.from}</span> → <span style={{ color: \"#0f0\" }}>{c.to}</span>",
|
|
840
|
+
" <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.from, marginLeft: 8, border: \"1px solid #333\" }} />",
|
|
841
|
+
" <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.to, marginLeft: 4, border: \"1px solid #333\" }} />",
|
|
842
|
+
" </div>",
|
|
843
|
+
" );",
|
|
844
|
+
" if (c.type === \"color_added\") return <div style={{ marginBottom: 8 }}><strong>{c.name}</strong> added: <code>{c.to}</code> <span style={{ display: \"inline-block\", width: 16, height: 16, backgroundColor: c.to, marginLeft: 4, border: \"1px solid #333\" }} /></div>;",
|
|
845
|
+
" if (c.type === \"color_removed\") return <div style={{ marginBottom: 8, color: \"#888\" }}><strong>{c.name}</strong> removed</div>;",
|
|
846
|
+
" if (c.type === \"typography_changed\") return <div style={{ marginBottom: 8 }}><strong>{c.key}</strong>: {c.from} → {c.to}</div>;",
|
|
847
|
+
" if (c.type === \"component_added\") return <div style={{ marginBottom: 8, color: \"#0f0\" }}>+ {c.name}</div>;",
|
|
848
|
+
" if (c.type === \"component_removed\") return <div style={{ marginBottom: 8, color: \"#f88\" }}>− {c.name}</div>;",
|
|
849
|
+
" return <div style={{ marginBottom: 8 }}>{c.type}: {JSON.stringify(c)}</div>;",
|
|
850
|
+
"}",
|
|
851
|
+
"",
|
|
852
|
+
"export const Default: Story = {",
|
|
853
|
+
" render: () => (",
|
|
854
|
+
" <div style={{ padding: 24, fontFamily: \"system-ui, sans-serif\" }}>",
|
|
855
|
+
" <h2 style={{ marginBottom: 16 }}>VDS Changelog</h2>",
|
|
856
|
+
" <div style={{ display: \"flex\", flexDirection: \"column\", gap: 24 }}>",
|
|
857
|
+
" {changelog.map((e, i) => (",
|
|
858
|
+
" <div key={i} style={{ border: \"1px solid #333\", borderRadius: 8, padding: 16, background: \"#111\" }}>",
|
|
859
|
+
" <div style={{ fontWeight: 600, marginBottom: 4 }}>v{e.version}</div>",
|
|
860
|
+
" <div style={{ fontSize: 12, color: \"#888\", marginBottom: 12 }}>{e.date}</div>",
|
|
861
|
+
" {e.changes.length === 0 ? <div style={{ color: \"#666\" }}>No changes</div> : (",
|
|
862
|
+
" <div>{e.changes.map((c, j) => <ChangeItem key={j} c={c} />)}</div>",
|
|
863
|
+
" )}",
|
|
864
|
+
" </div>",
|
|
865
|
+
" ))}",
|
|
866
|
+
" </div>",
|
|
867
|
+
" </div>",
|
|
868
|
+
" ),",
|
|
869
|
+
"};",
|
|
870
|
+
].join("\n");
|
|
871
|
+
fs.writeFileSync(path.join(foundationsDir, "Changelog.stories.tsx"), content, "utf-8");
|
|
872
|
+
console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "Changelog.stories.tsx")));
|
|
873
|
+
}
|
|
874
|
+
|
|
816
875
|
function main() {
|
|
817
876
|
if (!fs.existsSync(VDS_OUTPUT)) {
|
|
818
877
|
console.error("[VDS] vds-output.json not found. Run `npm run vds` first.");
|
|
@@ -832,6 +891,10 @@ function main() {
|
|
|
832
891
|
if (componentSuggestions?.length) {
|
|
833
892
|
writeComponentSuggestionsStory(componentSuggestions);
|
|
834
893
|
}
|
|
894
|
+
const changelog = data.changelog;
|
|
895
|
+
if (changelog?.length) {
|
|
896
|
+
writeChangelogStory(changelog);
|
|
897
|
+
}
|
|
835
898
|
try {
|
|
836
899
|
const fd = path.join(STORIES_DIR, "foundations");
|
|
837
900
|
if (fs.existsSync(fd)) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { watch } from 'fs';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
|
|
6
|
+
const ROOT = resolve(process.cwd());
|
|
7
|
+
const SRC = resolve(ROOT, 'src');
|
|
8
|
+
let timeout = null;
|
|
9
|
+
|
|
10
|
+
function run() {
|
|
11
|
+
const ts = new Date().toLocaleTimeString();
|
|
12
|
+
console.log(`\n[VDS ${ts}] Değişiklik algılandı, taranıyor...`);
|
|
13
|
+
try {
|
|
14
|
+
execSync('node vds-core/scan.mjs', { stdio: 'inherit', cwd: ROOT });
|
|
15
|
+
execSync('node vds-core/story-generator.mjs', { stdio: 'inherit', cwd: ROOT });
|
|
16
|
+
console.log(`[VDS ${ts}] ✅ Design system güncellendi.`);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
console.error(`[VDS ${ts}] ❌ Hata:`, e.message);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function onFileChange(eventType, filename) {
|
|
23
|
+
if (!filename) return;
|
|
24
|
+
if (filename.includes('stories/')) return;
|
|
25
|
+
if (filename.includes('vds-output')) return;
|
|
26
|
+
if (!filename.endsWith('.tsx') && !filename.endsWith('.ts') &&
|
|
27
|
+
!filename.endsWith('.css') && !filename.endsWith('.js')) return;
|
|
28
|
+
console.log(`[VDS] Değişiklik: ${filename}`);
|
|
29
|
+
clearTimeout(timeout);
|
|
30
|
+
timeout = setTimeout(run, 2000);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
run();
|
|
34
|
+
console.log('[VDS] 👀 src/ klasörü izleniyor...');
|
|
35
|
+
console.log('[VDS] Durdurmak için Ctrl+C\n');
|
|
36
|
+
watch(SRC, { recursive: true }, onFileChange);
|