vibe-design-system 2.5.49 → 2.5.51

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 CHANGED
@@ -194,12 +194,34 @@ function ensureStorybook(projectRoot) {
194
194
  fs.writeFileSync(mainPath, STORYBOOK_MAIN_TS, "utf-8");
195
195
  console.log("📝 .storybook/main.ts yazıldı.");
196
196
 
197
- const hasPreview = ["preview.tsx", "preview.ts", "preview.jsx", "preview.js"].some((name) =>
197
+ // preview.ts / preview.tsx eski VDS template'lerini otomatik olarak yeni router'sız template'e migrate et.
198
+ const previewCandidates = ["preview.tsx", "preview.ts", "preview.jsx", "preview.js"];
199
+ const existingPreview = previewCandidates.find((name) =>
198
200
  fs.existsSync(path.join(storybookDir, name))
199
201
  );
200
- if (!hasPreview) {
202
+ const previewPath = existingPreview ? path.join(storybookDir, existingPreview) : null;
203
+
204
+ if (!previewPath) {
205
+ // Daha önce hiç preview yoksa, yeni template'i yaz.
201
206
  fs.writeFileSync(path.join(storybookDir, "preview.ts"), STORYBOOK_PREVIEW_TS, "utf-8");
202
207
  console.log("📝 .storybook/preview.ts yazıldı.");
208
+ } else {
209
+ // Eski VDS preview'lerini tespit edip otomatik migrate et; kullanıcıya ait preview'lere dokunma.
210
+ try {
211
+ const content = fs.readFileSync(previewPath, "utf-8");
212
+ const looksLikeOldVdsPreview =
213
+ content.includes('MemoryRouter from "react-router-dom"') ||
214
+ content.includes("const withRouter") ||
215
+ content.includes("decorators: [withRouter");
216
+ if (looksLikeOldVdsPreview) {
217
+ fs.writeFileSync(previewPath, STORYBOOK_PREVIEW_TS, "utf-8");
218
+ console.log("📝 .storybook/preview.* eski VDS şablonundan yeni router'sız şablona güncellendi.");
219
+ } else {
220
+ console.log("ℹ️ .storybook/preview.* bulundu, kullanıcıya ait görünüyor; değiştirilmedi.");
221
+ }
222
+ } catch {
223
+ console.log("⚠️ .storybook/preview.* okunamadı; değiştirilmedi.");
224
+ }
203
225
  }
204
226
  }
205
227
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.5.49",
3
+ "version": "2.5.51",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -621,7 +621,77 @@ function extractComponentSuggestions() {
621
621
  reason: `Visual section candidate: same className cluster ${count}×, ${directChildren} child elements`,
622
622
  });
623
623
  }
624
- return suggestions;
624
+
625
+ // Ek: Tekil büyük bloklar (single large blocks) — tekrar etmese bile component adayı
626
+ const LARGE_BLOCK_MIN_CHILDREN = 5; // en az 5 direkt child
627
+ const LARGE_BLOCK_MIN_CLASS_TOKENS = 4; // className’de en az 4 token
628
+ const MAX_SINGLE_BLOCKS_PER_FILE = 3; // her dosyadan en fazla 3 aday
629
+
630
+ const singleBlockCandidates = [];
631
+
632
+ for (const { fullPath, srcRel } of allPageFiles) {
633
+ let content;
634
+ try {
635
+ content = fs.readFileSync(fullPath, "utf-8");
636
+ } catch {
637
+ continue;
638
+ }
639
+ const fileCandidates = [];
640
+ const reSingle = /className\s*=\s*["']([^"']+)["']|className\s*=\s*\{\s*["']([^"']+)["']\s*\}/g;
641
+ let m;
642
+ while ((m = reSingle.exec(content)) !== null) {
643
+ const raw = (m[1] ?? m[2] ?? "").trim().replace(/\s+/g, " ").trim();
644
+ if (!raw) continue;
645
+ const classCount = raw.split(/\s+/).filter(Boolean).length;
646
+ if (classCount < LARGE_BLOCK_MIN_CLASS_TOKENS) continue;
647
+
648
+ const before = content.substring(0, m.index);
649
+ const lastOpen = before.lastIndexOf("<");
650
+ const tagMatch = lastOpen >= 0 ? content.slice(lastOpen).match(/<(\w+)/) : null;
651
+ const tagName = tagMatch ? tagMatch[1] : "div";
652
+
653
+ let fullJsx = null;
654
+ let innerContent = "";
655
+ const extracted = extractFullElement(content, m.index, tagName);
656
+ if (extracted) {
657
+ fullJsx = extracted.fullJsx;
658
+ innerContent = extracted.innerContent || "";
659
+ }
660
+ const directChildren = countDirectChildren(innerContent);
661
+ if (directChildren < LARGE_BLOCK_MIN_CHILDREN) continue;
662
+
663
+ fileCandidates.push({
664
+ tagName,
665
+ pattern: raw,
666
+ fullJsx,
667
+ innerContent,
668
+ directChildren,
669
+ srcRel,
670
+ });
671
+ }
672
+
673
+ fileCandidates
674
+ .sort((a, b) => b.directChildren - a.directChildren)
675
+ .slice(0, MAX_SINGLE_BLOCKS_PER_FILE)
676
+ .forEach((c) => {
677
+ singleBlockCandidates.push({
678
+ suggestedName: sanitizeComponentName(
679
+ (suggestNameFromContent(c.innerContent) ||
680
+ suggestNameFromPattern(c.pattern) ||
681
+ "Section").replace(/\s+/g, "")
682
+ ),
683
+ tagName: c.tagName,
684
+ pattern: c.pattern,
685
+ fullJsx: c.fullJsx,
686
+ occurrences: 1,
687
+ foundIn: [c.srcRel],
688
+ snippet: `<${c.tagName} className="${c.pattern}">...</${c.tagName}>`,
689
+ reason: `Large visual block candidate: ${c.directChildren} direct children, rich className`,
690
+ });
691
+ });
692
+ }
693
+
694
+ return suggestions.concat(singleBlockCandidates);
625
695
  }
626
696
 
627
697
  /** src/pages/ içinde tanımlı ama src/components'a çıkarılmamış visual section'ları listele (component adayı raporu). */