UNPKG

ctx-gen

Version:

AI-Enhanced Documentation Generator for Code Understanding

136 lines 5.06 kB
import fs from 'fs-extra'; import path from 'path'; import { glob } from 'glob'; import { writeFileWithDir } from '../utils/fileUtils.js'; /** * Create an index file for the documentation * @param options - CtxGen options */ export async function createIndex(options) { // Get all markdown files in the modules directory const moduleDocs = await glob('**/*.md', { cwd: path.join(options.docsDir, 'modules'), ignore: ['index.md'], }); // Get diagrams if they exist const diagrams = await glob('**/*.mmd', { cwd: path.join(options.docsDir, 'diagrams'), ignore: [], }); // Generate the index content const indexContent = generateIndexContent(moduleDocs, diagrams, options); // Write the index file const indexPath = path.join(options.docsDir, 'index.md'); await writeFileWithDir(indexPath, indexContent); // Create a search index JSON file if machine formats are enabled if (options.machineFormats) { await createSearchIndex(options, moduleDocs); } } /** * Generate the content for the index file * @param moduleDocs - Array of module documentation file paths * @param diagrams - Array of diagram file paths * @param options - CtxGen options * @returns Index content as a string */ function generateIndexContent(moduleDocs, diagrams, options) { // Get package info if available let projectName = path.basename(process.cwd()); let projectDescription = ''; try { if (fs.existsSync('package.json')) { const packageInfo = fs.readJSONSync('package.json'); projectName = packageInfo.name || projectName; projectDescription = packageInfo.description || ''; } } catch (_error) { // Ignore errors } let content = `# ${projectName} Documentation\n\n`; if (projectDescription) { content += `${projectDescription}\n\n`; } content += `This documentation was generated with CtxGen on ${new Date().toLocaleDateString()}.\n\n`; // Add metadata section content += '## Project Metadata\n\n'; content += '- [Project Metadata](metadata.md)\n\n'; // Add modules section content += '## Modules\n\n'; if (moduleDocs.length > 0) { // Group modules by directory const groupedModules = {}; for (const doc of moduleDocs) { const dir = path.dirname(doc); if (!groupedModules[dir]) { groupedModules[dir] = []; } groupedModules[dir].push(doc); } // Add links to each module Object.entries(groupedModules).forEach(([dir, files]) => { if (dir !== '.') { content += `### ${dir}\n\n`; } files.forEach(file => { const moduleName = path.basename(file, '.md'); content += `- [${moduleName}](modules/${file})\n`; }); content += '\n'; }); } else { content += '*No modules found*\n\n'; } // Add diagrams section if available if (diagrams.length > 0) { content += '## Diagrams\n\n'; diagrams.forEach(diagram => { const diagramName = path.basename(diagram, '.mmd'); const formattedName = diagramName .split('_') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); content += `- [${formattedName}](diagrams/${diagram})\n`; }); content += '\n'; } // Add machine-readable formats section if enabled if (options.machineFormats) { content += '## Machine-Readable Formats\n\n'; content += '- [Metadata (JSON)](metadata.json)\n'; content += '- [Search Index (JSON)](search.json)\n'; content += '- [Analysis (JSON)](analysis.json)\n\n'; } return content; } /** * Create a search index JSON file for machine consumption * @param options - CtxGen options * @param moduleDocs - Array of module documentation file paths */ async function createSearchIndex(options, moduleDocs) { const searchIndex = {}; // Add each module document to the search index for (const doc of moduleDocs) { try { const content = await fs.readFile(path.join(options.docsDir, 'modules', doc), 'utf-8'); // Extract basic info const title = content.split('\n')[0].replace('# ', ''); // Create a simplified entry with key information searchIndex[doc] = { title, path: `modules/${doc}`, content: content.substring(0, 15000), // First 15000 chars for search }; } catch (error) { console.error(`Error adding ${doc} to search index:`, error); } } // Write the search index file const searchIndexPath = path.join(options.docsDir, 'search.json'); await writeFileWithDir(searchIndexPath, JSON.stringify(searchIndex, null, 2)); } //# sourceMappingURL=indexGenerator.js.map