import fs from 'fs'; import path from 'path'; /** * Script to consolidate all component documentation into AI-friendly manifests. * Updated to support modular domain-driven architecture. */ const DOCS_DIR = path.join(process.cwd(), 'docs', 'components'); const OUTPUT_FULL_TXT = path.join(process.cwd(), 'llms-full.txt'); const OUTPUT_JSON = path.join(process.cwd(), 'components.json'); const DOMAINS = ['ui', 'blocks', 'assistant', 'layout', 'brand']; function findSourcePath(componentName: string): string { // Try each domain for (const domain of DOMAINS) { // 1. Try folder-based structure (kebab-case folder) const folderPath = path.join(process.cwd(), 'components', domain, componentName); if (fs.existsSync(folderPath)) { // Check for index.ts or kebab-case.tsx const indexTs = path.join(folderPath, 'index.ts'); if (fs.existsSync(indexTs)) return `components/${domain}/${componentName}/index.ts`; const componentTsx = path.join(folderPath, `${componentName}.tsx`); if (fs.existsSync(componentTsx)) return `components/${domain}/${componentName}/${componentName}.tsx`; // Try PascalCase filename if kebab-case folder but PascalCase file const pascalName = componentName .split('-') .map(part => part.charAt(0).toUpperCase() + part.slice(1)) .join(''); const pascalTsx = path.join(folderPath, `${pascalName}.tsx`); if (fs.existsSync(pascalTsx)) return `components/${domain}/${componentName}/${pascalName}.tsx`; } // 2. Try direct file (kebab-case) const directFile = path.join(process.cwd(), 'components', domain, `${componentName}.tsx`); if (fs.existsSync(directFile)) return `components/${domain}/${componentName}.tsx`; } return `components/ui/${componentName}.tsx`; // Fallback to old behavior } function generate() { console.log('--- Generating AI Manifests ---'); if (!fs.existsSync(DOCS_DIR)) { console.error('Docs directory not found:', DOCS_DIR); return; } const files = fs .readdirSync(DOCS_DIR) .filter(f => f.endsWith('.md')) .sort(); console.log(`Found ${files.length} component documentation files.`); let fullContent = '# Xertica UI - Technical Documentation (Consolidated)\n\n'; fullContent += `> This file contains the full technical specification for all ${files.length} components of Xertica UI.\n`; fullContent += '> It is designed to be read by AI agents to provide a single source of truth context.\n\n'; const componentsIndex = []; for (const file of files) { const filePath = path.join(DOCS_DIR, file); const content = fs.readFileSync(filePath, 'utf-8'); const componentName = file.replace('.md', ''); // Add to full text fullContent += `\n--- START COMPONENT: ${componentName.toUpperCase()} ---\n`; fullContent += content; fullContent += `\n--- END COMPONENT: ${componentName.toUpperCase()} ---\n\n`; // Extract description const lines = content.split('\n'); let description = ''; // Look for first non-empty line after title const firstParaIdx = lines.findIndex( (l, i) => i > 0 && l.trim() !== '' && !l.startsWith('#') && !l.startsWith('---') ); if (firstParaIdx !== -1) { description = lines[firstParaIdx].trim(); } // Add to JSON index componentsIndex.push({ name: componentName, docPath: `docs/components/${file}`, sourcePath: findSourcePath(componentName), description: description, }); } // Write files fs.writeFileSync(OUTPUT_FULL_TXT, fullContent); fs.writeFileSync(OUTPUT_JSON, JSON.stringify(componentsIndex, null, 2)); console.log('✅ Generated llms-full.txt'); console.log('✅ Generated components.json'); } generate();