derm-ai / document_code.py
muhammadnoman76's picture
update
540cf5a
import os
from pathlib import Path
def generate_tree(path, prefix=""):
"""Generate tree structure"""
items = []
try:
entries = sorted(path.iterdir(), key=lambda x: (x.is_file(), x.name))
# Filter out ignored entries first
filtered_entries = [e for e in entries if not should_ignore(e)]
for i, entry in enumerate(filtered_entries):
is_last = i == len(filtered_entries) - 1
current_prefix = "└── " if is_last else "β”œβ”€β”€ "
items.append(f"{prefix}{current_prefix}{entry.name}")
if entry.is_dir():
next_prefix = prefix + (" " if is_last else "β”‚ ")
items.extend(generate_tree(entry, next_prefix))
except PermissionError:
pass
return items
def should_ignore(path):
"""Check if file/folder should be ignored"""
# Explicitly check for virtual environments and common ignored folders
if path.name in {'.venv', 'venv', '__pycache__', '.git', 'node_modules', '.idea', '.vscode'}:
return True
# Check if file is inside .venv or venv folder
if '.venv' in path.parts or 'venv' in path.parts:
return True
# Ignore all hidden files/folders (starting with .)
if path.name.startswith('.'):
return True
# Ignore specific files
ignore_files = {
'CODE_DOCUMENTATION.md', 'CODE_DOCUMENTATION.ipynb',
'CODE_DOCUMENTATION.html', 'CODE_DOCUMENTATION.pdf',
'CODE_DOCUMENTATION.docx', 'CODE_DOCUMENTATION.txt',
'CODE_DOCUMENTATION.csv', 'CODE_DOCUMENTATION.xlsx',
'CODE_DOCUMENTATION.pptx', 'CODE_DOCUMENTATION.ods',
'CODE_DOCUMENTATION.odp', 'CODE_DOCUMENTATION.odt',
'uv.lock', 'poetry.lock', 'Pipfile.lock',
'.DS_Store'
}
# Ignore by file extension
ignore_extensions = {'.pyc', '.pyo', '.pyd', '.so', '.egg-info'}
return (path.name in ignore_files or
path.suffix in ignore_extensions or
path.name.endswith('.egg-info'))
def get_code_files(directory):
"""Get all relevant code files"""
code_extensions = {'.py', '.js', '.ts', '.html', '.css', '.sql', '.yaml', '.yml', '.json', '.toml', '.cfg', '.ini'}
code_files = []
for file_path in directory.rglob("*"):
# Skip if it's a directory
if file_path.is_dir():
continue
# Skip ignored files/folders
if should_ignore(file_path):
continue
# Only include files with relevant extensions
if file_path.suffix.lower() in code_extensions:
code_files.append(file_path)
return sorted(code_files)
def main():
current_dir = Path.cwd()
output_file = current_dir / "CODE_DOCUMENTATION.md"
# Generate markdown
markdown = f"# {current_dir.name}\n\n"
markdown += f"Generated on: {Path.cwd()}\n\n"
# Add tree structure
markdown += "## Project Structure\n\n```\n"
markdown += f"{current_dir.name}/\n"
tree_items = generate_tree(current_dir)
for item in tree_items:
markdown += f"{item}\n"
markdown += "```\n\n"
# Get all code files
code_files = get_code_files(current_dir)
if code_files:
markdown += "## Source Code\n\n"
for file_path in code_files:
try:
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
rel_path = file_path.relative_to(current_dir)
file_extension = file_path.suffix.lstrip('.')
# Use appropriate syntax highlighting
if file_extension == 'py':
lang = 'python'
elif file_extension in ['js', 'ts']:
lang = 'javascript'
elif file_extension in ['html']:
lang = 'html'
elif file_extension in ['css']:
lang = 'css'
elif file_extension in ['sql']:
lang = 'sql'
elif file_extension in ['yaml', 'yml']:
lang = 'yaml'
elif file_extension in ['json']:
lang = 'json'
else:
lang = file_extension
markdown += f"### {rel_path}\n\n"
markdown += f"```{lang}\n{content}\n```\n\n"
except Exception as e:
markdown += f"### {rel_path}\n\n"
markdown += f"*Could not read file: {str(e)}*\n\n"
continue
else:
markdown += "## Source Code\n\n*No code files found.*\n\n"
# Write output
try:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(markdown)
print(f"βœ… Documentation generated successfully: {output_file}")
print(f"πŸ“ Total files documented: {len(code_files)}")
except Exception as e:
print(f"❌ Error writing documentation: {str(e)}")
if __name__ == "__main__":
main()