my extension
This commit is contained in:
commit
5eb12a79f9
1
.env
Normal file
1
.env
Normal file
@ -0,0 +1 @@
|
|||||||
|
MINDSDB_API_KEY="mdb_1ejiCDw9E5vMob0jFeqgfXOB2S2KqqboT09vq0TkreIw"
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.vscode-test/
|
||||||
|
*.vsix
|
5
.vscode-test.mjs
Normal file
5
.vscode-test.mjs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { defineConfig } from '@vscode/test-cli';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
files: 'test/**/*.test.js',
|
||||||
|
});
|
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the extensions.json format
|
||||||
|
"recommendations": [
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"ms-vscode.extension-test-runner"
|
||||||
|
]
|
||||||
|
}
|
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// A launch configuration that launches the extension inside a new window
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Run Extension",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
.vscodeignore
Normal file
16
.vscodeignore
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.vscode/**
|
||||||
|
.vscode-test/**
|
||||||
|
test/**
|
||||||
|
.gitignore
|
||||||
|
.yarnrc
|
||||||
|
vsc-extension-quickstart.md
|
||||||
|
**/jsconfig.json
|
||||||
|
**/*.map
|
||||||
|
**/eslint.config.mjs
|
||||||
|
**/.vscode-test.*
|
||||||
|
node_modules
|
||||||
|
**/*.map
|
||||||
|
.git
|
||||||
|
.github
|
||||||
|
.vscode
|
||||||
|
tests
|
9
CHANGELOG.md
Normal file
9
CHANGELOG.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to the "gendocx" extension will be documented in this file.
|
||||||
|
|
||||||
|
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Initial release
|
99
README.md
Normal file
99
README.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# GenDocX
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Next-Generation README Automation for Developers
|
||||||
|
|
||||||
|
GenDocX is a VS Code extension that automatically generates comprehensive, professional README files for your projects by analyzing your codebase using AI.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **One-Click README Generation**: Create detailed README.md files with a single command
|
||||||
|
- **Smart Project Analysis**: Automatically identifies technologies, dependencies, and key project features
|
||||||
|
- **Professional Documentation**: Creates well-structured, Markdown-formatted documentation that follows best practices
|
||||||
|
- **Comprehensive Content**: Includes project description, installation instructions, usage examples, API documentation, and more
|
||||||
|
- **Customizable Output**: Use the generated README as a solid foundation, then customize it to your needs
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Open VS Code
|
||||||
|
2. Go to the Extensions view (Ctrl+Shift+X)
|
||||||
|
3. Search for "GenDocX"
|
||||||
|
4. Click Install
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- VS Code 1.97.0 or newer
|
||||||
|
- A MindsDB API key (see Configuration section)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Open your project in VS Code
|
||||||
|
2. Run the command `GenDocX: Generate README` from the Command Palette (Ctrl+Shift+P)
|
||||||
|
3. If you haven't configured your API key yet, you'll be prompted to enter it
|
||||||
|
4. Wait while GenDocX analyzes your project and generates your README
|
||||||
|
5. Review and customize the generated README.md file
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
To set your MindsDB API key:
|
||||||
|
|
||||||
|
1. Run the command `GenDocX: Configure API Key` from the Command Palette
|
||||||
|
2. Enter your MindsDB API key when prompted
|
||||||
|
3. The key will be securely stored in your VS Code settings
|
||||||
|
|
||||||
|
Alternatively, you can set it in your settings.json file:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"gendocx.mindsdbApiKey": "your-api-key-here"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
GenDocX performs a comprehensive analysis of your codebase:
|
||||||
|
|
||||||
|
1. **Project Discovery**: Identifies main files, configuration files, and key source files
|
||||||
|
2. **Technology Detection**: Detects frameworks, libraries, and technologies used in your project
|
||||||
|
3. **Structure Analysis**: Maps your project's directory structure
|
||||||
|
4. **AI-Powered Documentation**: Utilizes MindsDB's AI to generate detailed, accurate documentation
|
||||||
|
5. **Markdown Formatting**: Structures the README with proper headings, code blocks, and formatting
|
||||||
|
|
||||||
|
## Extension Settings
|
||||||
|
|
||||||
|
This extension contributes the following settings:
|
||||||
|
|
||||||
|
* `gendocx.mindsdbApiKey`: MindsDB API key for README generation
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
- Currently supports JavaScript, TypeScript, Python, and other common languages. More specialized language support coming soon.
|
||||||
|
- Large projects may take more time to analyze.
|
||||||
|
|
||||||
|
## Release Notes
|
||||||
|
|
||||||
|
### 0.0.1
|
||||||
|
|
||||||
|
- Initial release
|
||||||
|
- Basic README generation functionality
|
||||||
|
- MindsDB integration
|
||||||
|
- Project structure analysis
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
|
||||||
|
GenDocX sends your project structure and sample code snippets to MindsDB for analysis. No data is stored beyond what's necessary for generating your README.
|
||||||
|
|
||||||
|
## Feedback and Contributions
|
||||||
|
|
||||||
|
- File bugs or feature requests on [GitHub](https://github.com/sneha-4-22/gendocx)
|
||||||
|
- Pull requests are welcome!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Made with ❤️ by Sneha Kumari
|
25
eslint.config.mjs
Normal file
25
eslint.config.mjs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import globals from "globals";
|
||||||
|
|
||||||
|
export default [{
|
||||||
|
files: ["**/*.js"],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.commonjs,
|
||||||
|
...globals.node,
|
||||||
|
...globals.mocha,
|
||||||
|
},
|
||||||
|
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
"no-const-assign": "warn",
|
||||||
|
"no-this-before-super": "warn",
|
||||||
|
"no-undef": "warn",
|
||||||
|
"no-unreachable": "warn",
|
||||||
|
"no-unused-vars": "warn",
|
||||||
|
"constructor-super": "warn",
|
||||||
|
"valid-typeof": "warn",
|
||||||
|
},
|
||||||
|
}];
|
449
extension.js
Normal file
449
extension.js
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
const vscode = require('vscode');
|
||||||
|
const fs = require('fs').promises;
|
||||||
|
const path = require('path');
|
||||||
|
const { OpenAI } = require('openai');
|
||||||
|
|
||||||
|
function createMindsDBClient(apiKey) {
|
||||||
|
return new OpenAI({
|
||||||
|
apiKey: apiKey || 'your-default-api-key',
|
||||||
|
baseURL: 'https://llm.mdb.ai/'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateReadmeWithMindsDB(rootPath, apiKey) {
|
||||||
|
try {
|
||||||
|
const mindsdb = createMindsDBClient(apiKey);
|
||||||
|
|
||||||
|
const packageInfo = await analyzePackageJson(rootPath);
|
||||||
|
const projectName = packageInfo?.name || path.basename(rootPath);
|
||||||
|
const projectVersion = packageInfo?.version || '1.0.0';
|
||||||
|
|
||||||
|
const projectFiles = await collectImportantFiles(rootPath);
|
||||||
|
|
||||||
|
const projectContext = await createProjectContext(rootPath, projectFiles, packageInfo);
|
||||||
|
|
||||||
|
const response = await mindsdb.chat.completions.create({
|
||||||
|
model: "gpt-3.5-turbo",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: `You are an expert software developer who specializes in analyzing codebases and creating detailed, accurate documentation.
|
||||||
|
You will be given information about a project codebase, and your task is to generate a comprehensive README.md file.
|
||||||
|
Focus on explaining what the project actually does, its main features, how it works, and its architecture.
|
||||||
|
Make the README professional, informative, and helpful for developers who want to understand or contribute to the project.`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: `Please analyze this project and generate a comprehensive README.md file:
|
||||||
|
|
||||||
|
PROJECT OVERVIEW:
|
||||||
|
${projectContext.overview}
|
||||||
|
|
||||||
|
KEY FILES:
|
||||||
|
${projectContext.keyFiles}
|
||||||
|
|
||||||
|
TECHNOLOGIES:
|
||||||
|
${projectContext.technologies}
|
||||||
|
|
||||||
|
PROJECT STRUCTURE:
|
||||||
|
${projectContext.structure}
|
||||||
|
|
||||||
|
Make sure to include:
|
||||||
|
1. A clear title and description that explains what the project actually does
|
||||||
|
2. Key features with meaningful descriptions
|
||||||
|
3. Installation instructions
|
||||||
|
4. Usage examples
|
||||||
|
5. API documentation (if applicable)
|
||||||
|
6. Information about the architecture
|
||||||
|
7. Prerequisites
|
||||||
|
8. License information
|
||||||
|
|
||||||
|
Structure the README with proper Markdown formatting, including headings, code blocks, and bullet points.`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
max_tokens: 4000,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.choices[0].message.content;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error generating README with MindsDB:", error);
|
||||||
|
throw new Error(`Failed to generate README with MindsDB: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function collectImportantFiles(rootPath, maxFilesToAnalyze = 20) {
|
||||||
|
const result = {
|
||||||
|
mainFiles: [],
|
||||||
|
configFiles: [],
|
||||||
|
sourceFiles: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const mainFilePatterns = [
|
||||||
|
'index.js', 'app.js', 'main.py', 'app.py', 'index.jsx', 'app.jsx',
|
||||||
|
'src/index.js', 'src/app.js', 'src/main.py', 'src/app.py', 'src/index.jsx', 'src/app.jsx'
|
||||||
|
];
|
||||||
|
|
||||||
|
const configFilePatterns = [
|
||||||
|
'package.json', 'tsconfig.json', 'webpack.config.js', '.env.example',
|
||||||
|
'Dockerfile', 'docker-compose.yml', 'requirements.txt', 'setup.py',
|
||||||
|
'pyproject.toml', 'go.mod', 'pom.xml', 'build.gradle'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const pattern of mainFilePatterns) {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(rootPath, pattern);
|
||||||
|
await fs.access(filePath);
|
||||||
|
result.mainFiles.push(pattern);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pattern of configFilePatterns) {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(rootPath, pattern);
|
||||||
|
await fs.access(filePath);
|
||||||
|
result.configFiles.push(pattern);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
await findSourceFiles(rootPath, '', result.sourceFiles, maxFilesToAnalyze);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findSourceFiles(rootPath, relativePath, sourceFiles, maxFiles) {
|
||||||
|
if (sourceFiles.length >= maxFiles) return;
|
||||||
|
|
||||||
|
const currentPath = path.join(rootPath, relativePath);
|
||||||
|
try {
|
||||||
|
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
||||||
|
|
||||||
|
entries.sort((a, b) => {
|
||||||
|
const aIsPriority = a.isDirectory() && ['src', 'app', 'lib', 'main'].includes(a.name);
|
||||||
|
const bIsPriority = b.isDirectory() && ['src', 'app', 'lib', 'main'].includes(b.name);
|
||||||
|
return (bIsPriority ? 1 : 0) - (aIsPriority ? 1 : 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (sourceFiles.length >= maxFiles) return;
|
||||||
|
|
||||||
|
const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
||||||
|
|
||||||
|
if (
|
||||||
|
entry.name.startsWith('.') ||
|
||||||
|
['node_modules', 'dist', 'build', '__pycache__', 'venv', 'env', '.git'].includes(entry.name)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
await findSourceFiles(rootPath, entryRelativePath, sourceFiles, maxFiles);
|
||||||
|
} else if (isSourceFile(entry.name)) {
|
||||||
|
sourceFiles.push(entryRelativePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error scanning directory ${currentPath}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSourceFile(filename) {
|
||||||
|
const sourceExtensions = [
|
||||||
|
'.js', '.jsx', '.ts', '.tsx', '.py', '.go', '.java',
|
||||||
|
'.html', '.css', '.scss', '.sass', '.less', '.php', '.rb'
|
||||||
|
];
|
||||||
|
const ext = path.extname(filename).toLowerCase();
|
||||||
|
return sourceExtensions.includes(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function analyzePackageJson(rootPath) {
|
||||||
|
try {
|
||||||
|
const packagePath = path.join(rootPath, 'package.json');
|
||||||
|
const packageData = await fs.readFile(packagePath, 'utf8');
|
||||||
|
const packageJson = JSON.parse(packageData);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: packageJson.name,
|
||||||
|
description: packageJson.description,
|
||||||
|
version: packageJson.version,
|
||||||
|
dependencies: packageJson.dependencies || {},
|
||||||
|
devDependencies: packageJson.devDependencies || {},
|
||||||
|
scripts: packageJson.scripts || {}
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
const pyprojectPath = path.join(rootPath, 'pyproject.toml');
|
||||||
|
const pyprojectData = await fs.readFile(pyprojectPath, 'utf8');
|
||||||
|
|
||||||
|
const nameMatch = pyprojectData.match(/name\s*=\s*["']([^"']+)["']/);
|
||||||
|
const versionMatch = pyprojectData.match(/version\s*=\s*["']([^"']+)["']/);
|
||||||
|
const descriptionMatch = pyprojectData.match(/description\s*=\s*["']([^"']+)["']/);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: nameMatch ? nameMatch[1] : null,
|
||||||
|
description: descriptionMatch ? descriptionMatch[1] : null,
|
||||||
|
version: versionMatch ? versionMatch[1] : null
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createProjectContext(rootPath, projectFiles, packageInfo) {
|
||||||
|
const context = {
|
||||||
|
overview: "Unknown project",
|
||||||
|
keyFiles: "",
|
||||||
|
technologies: "",
|
||||||
|
structure: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
if (packageInfo) {
|
||||||
|
context.overview = `Project Name: ${packageInfo.name || 'Unknown'}\n`;
|
||||||
|
context.overview += `Version: ${packageInfo.version || 'Unknown'}\n`;
|
||||||
|
context.overview += `Description: ${packageInfo.description || 'No description provided'}\n\n`;
|
||||||
|
|
||||||
|
if (packageInfo.dependencies || packageInfo.devDependencies) {
|
||||||
|
context.overview += "Dependencies:\n";
|
||||||
|
|
||||||
|
const allDeps = { ...packageInfo.dependencies, ...packageInfo.devDependencies };
|
||||||
|
const technologies = Object.keys(allDeps).slice(0, 15);
|
||||||
|
context.overview += technologies.map(tech => `- ${tech}`).join('\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
context.overview = `Project Name: ${path.basename(rootPath)}\n`;
|
||||||
|
context.overview += "No package.json or similar project definition file found.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
context.keyFiles = "Key file contents:\n\n";
|
||||||
|
for (const file of [...projectFiles.mainFiles, ...projectFiles.configFiles].slice(0, 5)) {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(rootPath, file);
|
||||||
|
const content = await fs.readFile(filePath, 'utf8');
|
||||||
|
context.keyFiles += `--- FILE: ${file} ---\n\n${content.substring(0, 5000)}\n\n`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error reading file ${file}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of projectFiles.sourceFiles.slice(0, 10)) {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(rootPath, file);
|
||||||
|
const content = await fs.readFile(filePath, 'utf8');
|
||||||
|
context.keyFiles += `--- FILE: ${file} ---\n\n${content.substring(0, 3000)}\n\n`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error reading file ${file}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.technologies = await detectTechnologies(rootPath, projectFiles, packageInfo);
|
||||||
|
|
||||||
|
context.structure = await generateProjectStructure(rootPath);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function detectTechnologies(rootPath, projectFiles, packageInfo) {
|
||||||
|
const technologies = new Set();
|
||||||
|
|
||||||
|
if (packageInfo && packageInfo.dependencies) {
|
||||||
|
if (packageInfo.dependencies.react) technologies.add("React");
|
||||||
|
if (packageInfo.dependencies.vue) technologies.add("Vue.js");
|
||||||
|
if (packageInfo.dependencies.express) technologies.add("Express.js");
|
||||||
|
if (packageInfo.dependencies.next) technologies.add("Next.js");
|
||||||
|
if (packageInfo.dependencies['@angular/core']) technologies.add("Angular");
|
||||||
|
|
||||||
|
if (packageInfo.dependencies.mongoose || packageInfo.dependencies.mongodb) technologies.add("MongoDB");
|
||||||
|
if (packageInfo.dependencies.mysql || packageInfo.dependencies.mysql2) technologies.add("MySQL");
|
||||||
|
if (packageInfo.dependencies.pg || packageInfo.dependencies.postgresql) technologies.add("PostgreSQL");
|
||||||
|
if (packageInfo.dependencies.sequelize) technologies.add("Sequelize");
|
||||||
|
if (packageInfo.dependencies.prisma) technologies.add("Prisma");
|
||||||
|
|
||||||
|
if (packageInfo.dependencies.redux || packageInfo.dependencies['@reduxjs/toolkit']) technologies.add("Redux");
|
||||||
|
if (packageInfo.dependencies['styled-components']) technologies.add("Styled Components");
|
||||||
|
if (packageInfo.dependencies.electron) technologies.add("Electron");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const file of [...projectFiles.mainFiles, ...projectFiles.sourceFiles]) {
|
||||||
|
const ext = path.extname(file).toLowerCase();
|
||||||
|
|
||||||
|
if (ext === '.js' || ext === '.jsx') technologies.add("JavaScript");
|
||||||
|
if (ext === '.ts' || ext === '.tsx') technologies.add("TypeScript");
|
||||||
|
if (ext === '.py') technologies.add("Python");
|
||||||
|
if (ext === '.go') technologies.add("Go");
|
||||||
|
if (ext === '.java') technologies.add("Java");
|
||||||
|
if (ext === '.php') technologies.add("PHP");
|
||||||
|
if (ext === '.rb') technologies.add("Ruby");
|
||||||
|
if (ext === '.css') technologies.add("CSS");
|
||||||
|
if (ext === '.scss' || ext === '.sass') technologies.add("Sass");
|
||||||
|
if (ext === '.html') technologies.add("HTML");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filePath = path.join(rootPath, file);
|
||||||
|
const content = await fs.readFile(filePath, 'utf8');
|
||||||
|
|
||||||
|
if (content.includes('import React') || content.includes('from "react"') || content.includes("from 'react'"))
|
||||||
|
technologies.add("React");
|
||||||
|
|
||||||
|
if (content.includes('import Vue') || content.includes('new Vue('))
|
||||||
|
technologies.add("Vue.js");
|
||||||
|
|
||||||
|
if (content.includes('import { Injectable }') || content.includes('@Component'))
|
||||||
|
technologies.add("Angular");
|
||||||
|
|
||||||
|
if (content.includes('import express') || content.includes("require('express')"))
|
||||||
|
technologies.add("Express.js");
|
||||||
|
|
||||||
|
if (content.includes('import flask') || content.includes('from flask import'))
|
||||||
|
technologies.add("Flask");
|
||||||
|
|
||||||
|
if (content.includes('import django') || content.includes('from django'))
|
||||||
|
technologies.add("Django");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error analyzing file ${file}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(path.join(rootPath, 'Dockerfile'));
|
||||||
|
technologies.add("Docker");
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(path.join(rootPath, 'docker-compose.yml'));
|
||||||
|
technologies.add("Docker Compose");
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const reqPath = path.join(rootPath, 'requirements.txt');
|
||||||
|
const requirements = await fs.readFile(reqPath, 'utf8');
|
||||||
|
|
||||||
|
if (requirements.includes('django')) technologies.add("Django");
|
||||||
|
if (requirements.includes('flask')) technologies.add("Flask");
|
||||||
|
if (requirements.includes('fastapi')) technologies.add("FastAPI");
|
||||||
|
if (requirements.includes('tensorflow') || requirements.includes('keras')) technologies.add("TensorFlow");
|
||||||
|
if (requirements.includes('torch') || requirements.includes('pytorch')) technologies.add("PyTorch");
|
||||||
|
if (requirements.includes('pandas')) technologies.add("Pandas");
|
||||||
|
if (requirements.includes('numpy')) technologies.add("NumPy");
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return Array.from(technologies).join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateProjectStructure(rootPath) {
|
||||||
|
let structure = "";
|
||||||
|
|
||||||
|
async function scanDir(dir, indent = "") {
|
||||||
|
try {
|
||||||
|
const entries = await fs.readdir(path.join(rootPath, dir), { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.name.startsWith('.') ||
|
||||||
|
['node_modules', '__pycache__', 'venv', 'env', '.git', 'build', 'dist'].includes(entry.name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const relativePath = dir ? `${dir}/${entry.name}` : entry.name;
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
structure += `${indent}- ${entry.name}/\n`;
|
||||||
|
await scanDir(relativePath, indent + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error generating structure for ${dir}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await scanDir("");
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
function activate(context) {
|
||||||
|
let disposable = vscode.commands.registerCommand(
|
||||||
|
'gendocx.generateReadme',
|
||||||
|
async () => {
|
||||||
|
try {
|
||||||
|
const rootPath = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||||
|
if (!rootPath) {
|
||||||
|
throw new Error('No active workspace found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = vscode.workspace.getConfiguration('gendocx');
|
||||||
|
let apiKey = config.get('mindsdbApiKey');
|
||||||
|
|
||||||
|
if (!apiKey) {
|
||||||
|
apiKey = await vscode.window.showInputBox({
|
||||||
|
prompt: "Enter your API key (you can save this in settings later)",
|
||||||
|
password: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!apiKey) {
|
||||||
|
vscode.window.showWarningMessage('MindsDB API key is required to generate README');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await vscode.window.withProgress(
|
||||||
|
{
|
||||||
|
location: vscode.ProgressLocation.Notification,
|
||||||
|
title: 'Analyzing project and generating README...',
|
||||||
|
cancellable: false,
|
||||||
|
},
|
||||||
|
async (progress) => {
|
||||||
|
progress.report({ message: 'Collecting project information...' });
|
||||||
|
|
||||||
|
progress.report({ message: 'Analyzing codebase with AI...' });
|
||||||
|
const readmeContent = await generateReadmeWithMindsDB(rootPath, apiKey);
|
||||||
|
|
||||||
|
const readmePath = path.join(rootPath, 'README.md');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(readmePath);
|
||||||
|
const overwrite = await vscode.window.showQuickPick(['Yes', 'No'], {
|
||||||
|
placeHolder: 'README.md already exists. Overwrite?'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (overwrite !== 'Yes') {
|
||||||
|
vscode.window.showInformationMessage('README generation cancelled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
await fs.writeFile(readmePath, readmeContent.trim());
|
||||||
|
const doc = await vscode.workspace.openTextDocument(readmePath);
|
||||||
|
await vscode.window.showTextDocument(doc);
|
||||||
|
|
||||||
|
vscode.window.showInformationMessage('README.md generated successfully!');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
vscode.window.showErrorMessage(`Error: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let configDisposable = vscode.commands.registerCommand(
|
||||||
|
'gendocx.configureApiKey',
|
||||||
|
async () => {
|
||||||
|
const apiKey = await vscode.window.showInputBox({
|
||||||
|
prompt: "Enter your MindsDB API key",
|
||||||
|
password: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (apiKey) {
|
||||||
|
const config = vscode.workspace.getConfiguration('gendocx');
|
||||||
|
await config.update('mindsdbApiKey', apiKey, true);
|
||||||
|
vscode.window.showInformationMessage('MindsDB API key saved!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
context.subscriptions.push(disposable, configDisposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deactivate() {}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
activate,
|
||||||
|
deactivate
|
||||||
|
};
|
13
jsconfig.json
Normal file
13
jsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "Node16",
|
||||||
|
"target": "ES2022",
|
||||||
|
"checkJs": true, /* Typecheck .js files. */
|
||||||
|
"lib": [
|
||||||
|
"ES2022"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
3284
package-lock.json
generated
Normal file
3284
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
57
package.json
Normal file
57
package.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"name": "gendocx",
|
||||||
|
"publisher": "Sneha",
|
||||||
|
"displayName": "GenDocX",
|
||||||
|
"description": "Next-gen README automation ",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.97.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Other"
|
||||||
|
],
|
||||||
|
"activationEvents": [
|
||||||
|
"onStartupFinished"
|
||||||
|
],
|
||||||
|
"main": "./extension.js",
|
||||||
|
"contributes": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "gendocx.generateReadme",
|
||||||
|
"title": "Generate README with GenDocX"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "gendocx.configureApiKey",
|
||||||
|
"title": "Configure GenDocX API Key"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration": {
|
||||||
|
"title": "GenDocX",
|
||||||
|
"properties": {
|
||||||
|
"gendocx.mindsApiKey": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "",
|
||||||
|
"description": "MindsDB API Key for README generation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"pretest": "npm run lint",
|
||||||
|
"test": "vscode-test"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/mocha": "^10.0.10",
|
||||||
|
"@types/node": "20.x",
|
||||||
|
"@types/vscode": "^1.97.0",
|
||||||
|
"@vscode/test-cli": "^0.0.10",
|
||||||
|
"@vscode/test-electron": "^2.4.1",
|
||||||
|
"eslint": "^9.19.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.7.9",
|
||||||
|
"gendocx": "file:",
|
||||||
|
"openai": "^4.85.4"
|
||||||
|
}
|
||||||
|
}
|
15
test/extension.test.js
Normal file
15
test/extension.test.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
// You can import and use all API from the 'vscode' module
|
||||||
|
// as well as import your extension to test it
|
||||||
|
const vscode = require('vscode');
|
||||||
|
// const myExtension = require('../extension');
|
||||||
|
|
||||||
|
suite('Extension Test Suite', () => {
|
||||||
|
vscode.window.showInformationMessage('Start all tests.');
|
||||||
|
|
||||||
|
test('Sample test', () => {
|
||||||
|
assert.strictEqual(-1, [1, 2, 3].indexOf(5));
|
||||||
|
assert.strictEqual(-1, [1, 2, 3].indexOf(0));
|
||||||
|
});
|
||||||
|
});
|
112
vsc-extension-quickstart.md
Normal file
112
vsc-extension-quickstart.md
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# GenDocX - VS Code Extension
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
GenDocX is a VS Code extension that automates the creation of professional README files for software projects. By analyzing your codebase with AI, it generates comprehensive documentation that explains your project's purpose, features, architecture, and usage.
|
||||||
|
|
||||||
|
## Features in Detail
|
||||||
|
|
||||||
|
### Intelligent Project Analysis
|
||||||
|
|
||||||
|
GenDocX performs a multi-layered analysis of your project:
|
||||||
|
|
||||||
|
- **Configuration Detection**: Identifies package.json, requirements.txt, and other configuration files
|
||||||
|
- **Technology Identification**: Detects frameworks (React, Vue, Angular, Express, Django, etc.)
|
||||||
|
- **Dependency Mapping**: Lists and categorizes your project dependencies
|
||||||
|
- **Entry Point Location**: Finds main application files and entry points
|
||||||
|
- **Directory Structure**: Maps the overall architecture of your project
|
||||||
|
|
||||||
|
### Professional Documentation Generation
|
||||||
|
|
||||||
|
The extension creates READMEs with:
|
||||||
|
|
||||||
|
- **Project Title and Description**: Clear explanation of what your project does
|
||||||
|
- **Feature Lists**: Comprehensive breakdown of key functionality
|
||||||
|
- **Installation Instructions**: Step-by-step setup guidance
|
||||||
|
- **Usage Examples**: Code samples showing how to use your project
|
||||||
|
- **API Documentation**: Function/endpoint documentation when applicable
|
||||||
|
- **Architecture Information**: Explains how components fit together
|
||||||
|
- **Prerequisites**: Lists required tools and dependencies
|
||||||
|
- **License Information**: Includes appropriate licensing details
|
||||||
|
|
||||||
|
### MindsDB Integration
|
||||||
|
|
||||||
|
GenDocX uses MindsDB's AI capabilities to:
|
||||||
|
|
||||||
|
- Parse and understand your codebase
|
||||||
|
- Identify patterns and architectural choices
|
||||||
|
- Generate natural language explanations
|
||||||
|
- Structure information in a developer-friendly format
|
||||||
|
|
||||||
|
## Extension Development
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
The extension consists of these key components:
|
||||||
|
|
||||||
|
- **activation**: Registers VS Code commands and sets up event handlers
|
||||||
|
- **collectImportantFiles**: Identifies key files in the project
|
||||||
|
- **analyzePackageJson**: Extracts metadata from package.json or similar
|
||||||
|
- **createProjectContext**: Builds a comprehensive context about the project
|
||||||
|
- **detectTechnologies**: Identifies technologies and frameworks
|
||||||
|
- **generateProjectStructure**: Maps the directory structure
|
||||||
|
- **generateReadmeWithMindsDB**: Handles API communication with MindsDB
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
The extension provides two commands:
|
||||||
|
|
||||||
|
1. `gendocx.generateReadme`: Analyzes the project and generates a README
|
||||||
|
2. `gendocx.configureApiKey`: Saves the MindsDB API key in settings
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
|
||||||
|
- `gendocx.mindsdbApiKey`: Stores the MindsDB API key securely
|
||||||
|
|
||||||
|
## Development Setup
|
||||||
|
|
||||||
|
1. Clone the repository
|
||||||
|
2. Run `npm install` to install dependencies
|
||||||
|
3. Press F5 in VS Code to run the extension in development mode
|
||||||
|
|
||||||
|
## Building and Publishing
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint
|
||||||
|
vsce package
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a `.vsix` file that can be installed locally.
|
||||||
|
|
||||||
|
### Publishing
|
||||||
|
|
||||||
|
To publish to the VS Code Marketplace:
|
||||||
|
|
||||||
|
1. Create a personal access token (PAT) in Azure DevOps
|
||||||
|
2. Install vsce: `npm install -g @vscode/vsce`
|
||||||
|
3. Log in: `vsce login YourPublisherName`
|
||||||
|
4. Publish: `vsce publish`
|
||||||
|
|
||||||
|
## Technical Notes
|
||||||
|
|
||||||
|
- The extension requires a connection to MindsDB's API
|
||||||
|
- API keys are stored securely in VS Code's settings storage
|
||||||
|
- The extension can analyze JavaScript, TypeScript, Python, and other common languages
|
||||||
|
|
||||||
|
## Debugging Tips
|
||||||
|
|
||||||
|
- Check VS Code's Output panel for extension logs
|
||||||
|
- Ensure your MindsDB API key is correctly configured
|
||||||
|
- For large projects, the analysis might take more time
|
||||||
|
|
||||||
|
## Future Development
|
||||||
|
|
||||||
|
Planned features include:
|
||||||
|
|
||||||
|
- Custom README templates
|
||||||
|
- Support for more specialized languages and frameworks
|
||||||
|
- Ability to update existing READMEs
|
||||||
|
- Integration with other documentation platforms
|
||||||
|
- Additional document types (Contributing guidelines, API docs, etc.)
|
Loading…
x
Reference in New Issue
Block a user