ctx-gen
Version:
AI-Enhanced Documentation Generator for Code Understanding
136 lines • 5.06 kB
JavaScript
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