const fs = require('fs'); const path = require('path'); // Read the original registry const registryPath = path.join(__dirname, 'registry.json'); const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8')); // Create output directories const registryDir = path.join(__dirname, 'registry'); const componentsDir = path.join(registryDir, 'components'); const schemasDir = path.join(registryDir, 'schemas'); [componentsDir, schemasDir].forEach(dir => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } }); // Extract intent from description/details function extractIntent(description, details, name) { const text = `${description} ${details}`.toLowerCase(); // More specific intent extraction if (text.includes('vertical stack') && text.includes('alternating')) return 'sequential vertical steps with alternating layout'; if (text.includes('horizontal') && text.includes('timeline')) return 'horizontal timeline'; if (text.includes('vertical') && text.includes('sticky') && text.includes('scroll')) return 'vertical sticky scroll timeline'; if (text.includes('hero') || text.includes('landing')) return 'hero with media'; if (text.includes('sequential') || (text.includes('step') && text.includes('process'))) return 'sequential process'; if (text.includes('feature') && !text.includes('hero')) return 'feature showcase'; if (text.includes('pricing') || text.includes('plan')) return 'pricing plans'; if (text.includes('testimonial') || text.includes('review')) return 'testimonials'; if (text.includes('about') || text.includes('company')) return 'about section'; if (text.includes('blog') || text.includes('article')) return 'content listing'; if (text.includes('contact') || text.includes('form')) return 'contact form'; if (text.includes('faq') || text.includes('question')) return 'faq section'; if (text.includes('footer')) return 'footer'; if (text.includes('metric') || text.includes('kpi') || text.includes('statistic')) return 'metrics display'; if (text.includes('product') && !text.includes('feature')) return 'product showcase'; if (text.includes('team') || text.includes('member')) return 'team section'; if (text.includes('carousel') || text.includes('gallery')) return 'media carousel'; if (text.includes('grid') && text.includes('card')) return 'card grid'; if (text.includes('timeline')) return 'timeline'; if (text.includes('split') && text.includes('layout')) return 'split layout'; if (text.includes('background')) return 'background'; if (text.includes('button')) return 'button'; if (text.includes('navbar') || text.includes('navigation')) return 'navigation'; if (text.includes('text') && !text.includes('button')) return 'text component'; if (text.includes('form') || text.includes('input')) return 'form'; return 'general component'; } // Extract bestFor from description/details function extractBestFor(description, details) { const text = `${description} ${details}`.toLowerCase(); const bestFor = []; if (text.includes('landing page') || text.includes('hero')) bestFor.push('landing pages'); if (text.includes('process') || text.includes('step')) bestFor.push('process flows', 'roadmaps', 'step-by-step explanation'); if (text.includes('feature')) bestFor.push('feature showcases', 'capability displays'); if (text.includes('pricing')) bestFor.push('pricing pages', 'subscription tiers'); if (text.includes('portfolio') || text.includes('gallery')) bestFor.push('portfolios', 'image galleries'); if (text.includes('testimonial')) bestFor.push('social proof', 'customer reviews'); if (text.includes('about')) bestFor.push('about pages', 'company information'); if (text.includes('blog')) bestFor.push('blog listings', 'article grids'); if (text.includes('contact')) bestFor.push('contact pages', 'lead generation'); if (text.includes('faq')) bestFor.push('help pages', 'support sections'); if (text.includes('metric') || text.includes('kpi')) bestFor.push('statistics displays', 'achievement showcases'); if (text.includes('product')) bestFor.push('product catalogs', 'e-commerce'); if (text.includes('team')) bestFor.push('team pages', 'staff directories'); return bestFor.length > 0 ? bestFor : ['general use']; } // Extract avoidWhen from constraints and details function extractAvoidWhen(details, constraints) { const avoidWhen = []; const text = details.toLowerCase(); if (text.includes('requires') && text.includes('5+')) avoidWhen.push('less than 5 items'); if (text.includes('requires') && text.includes('3-5')) avoidWhen.push('less than 3 items', 'more than 5 items'); if (text.includes('single') && !text.includes('multiple')) avoidWhen.push('multiple items'); if (text.includes('sequential') || text.includes('step')) avoidWhen.push('non-sequential content', 'single item'); if (text.includes('grid') && !text.includes('carousel')) avoidWhen.push('more than 4 items'); if (text.includes('carousel') && !text.includes('grid')) avoidWhen.push('less than 5 items'); if (constraints?.itemRules) { if (constraints.itemRules.minItems > 1) { avoidWhen.push(`less than ${constraints.itemRules.minItems} items`); } if (constraints.itemRules.maxItems) { avoidWhen.push(`more than ${constraints.itemRules.maxItems} items`); } } return avoidWhen.length > 0 ? avoidWhen : []; } // Extract requires from constraints and propsSchema function extractRequires(constraints, propsSchema) { const requires = []; // Check propsSchema for array props (main data requirements) if (propsSchema) { for (const [key, value] of Object.entries(propsSchema)) { if (typeof value === 'string' && value.includes('Array') && !key.includes('ClassName') && key !== 'className') { requires.push(`${key}[]`); } } } // Add item constraints if no array props found if (requires.length === 0 && constraints?.itemRules?.minItems) { requires.push(`minimum ${constraints.itemRules.minItems} items`); } return requires; } // Extract import path from import statement function extractImportPath(importStatement) { if (!importStatement) return ''; // Extract path from: import Component from '@/path/to/Component'; const match = importStatement.match(/from\s+['"]([^'"]+)['"]/); return match ? match[1] : importStatement; } // Simplify propsSchema - remove className props function simplifyPropsSchema(propsSchema) { if (!propsSchema) return {}; const simplified = {}; for (const [key, value] of Object.entries(propsSchema)) { // Skip className props if (!key.includes('ClassName') && key !== 'className') { simplified[key] = value; } } return simplified; } // Process all components const indexData = {}; const intentsMap = {}; const allComponents = []; // Process componentRegistry Object.keys(registry.componentRegistry || {}).forEach(category => { registry.componentRegistry[category].forEach(component => { allComponents.push({ ...component, category, type: 'component' }); }); }); // Process sectionRegistry Object.keys(registry.sectionRegistry || {}).forEach(category => { registry.sectionRegistry[category].forEach(component => { allComponents.push({ ...component, category, type: 'section' }); }); }); // Process each component allComponents.forEach(component => { const name = component.name; const intent = extractIntent(component.description, component.details, name); const bestFor = extractBestFor(component.description, component.details); const avoidWhen = extractAvoidWhen(component.details, component.constraints); const requires = extractRequires(component.constraints, component.propsSchema); const importPath = extractImportPath(component.import); // Add to index.json (lightweight catalog) indexData[name] = { category: component.category, intent: intent, bestFor: bestFor, avoidWhen: avoidWhen, requires: requires, import: importPath }; // Add to intents map if (!intentsMap[intent]) { intentsMap[intent] = []; } if (!intentsMap[intent].includes(name)) { intentsMap[intent].push(name); } // Create component detail file const componentData = { name: name, description: component.description, constraints: component.constraints || {}, propsSchema: simplifyPropsSchema(component.propsSchema), usageExample: component.usage || '', do: [ ...bestFor.map(bf => `Use for ${bf}`), ...requires.map(r => `Requires ${r}`) ], dont: [ ...avoidWhen.map(aw => `Do not use ${aw}`) ], editRules: { textOnly: true, layoutLocked: true, styleLocked: true } }; fs.writeFileSync( path.join(componentsDir, `${name}.json`), JSON.stringify(componentData, null, 2) ); // Create schema file (full propsSchema) const schemaData = { name: name, propsSchema: component.propsSchema || {} }; fs.writeFileSync( path.join(schemasDir, `${name}.schema.json`), JSON.stringify(schemaData, null, 2) ); }); // Write index.json fs.writeFileSync( path.join(registryDir, 'index.json'), JSON.stringify(indexData, null, 2) ); // Write intents.json fs.writeFileSync( path.join(registryDir, 'intents.json'), JSON.stringify(intentsMap, null, 2) ); console.log(`✅ Created LLM-friendly registry structure:`); console.log(` - ${Object.keys(indexData).length} components in index.json`); console.log(` - ${Object.keys(intentsMap).length} intent mappings in intents.json`); console.log(` - ${allComponents.length} component detail files`); console.log(` - ${allComponents.length} schema files`);