scripts-fix-markdown-issues
#!/usr/bin/env python3 """
title: Fix Markdown Issues Script component_type: script version: 1.0.0 author: CODITECT Framework Team summary: Automatically fixes common markdown issues including trailing whitespace, mermaid tags, and HTML entities tags: ['markdown', 'fix', 'cleanup', 'documentation'] moe_confidence: 0.910 moe_classified: '2026-01-29' moe_type_expert: documentation-expert related_components:
- script: audit-markdown
- agent: markdown-mermaid-cleaner
- command: markdown-cleanup
Fix Common Markdown Issues
Automatically fixes:
- Trailing whitespace
to
in mermaid diagrams- Unclosed code block markers
- Inconsistent heading levels
Usage: python3 scripts/fix-markdown-issues.py <file_or_directory> """
import argparse import re import sys from pathlib import Path
def fix_trailing_whitespace(content: str) -> str: """Remove trailing whitespace from all lines.""" lines = content.split('\n') lines = [line.rstrip() for line in lines] return '\n'.join(lines)
def fix_mermaid_br_tags(content: str) -> str:
"""Fix
tags in mermaid diagrams to use
or \n."""
lines = content.split('\n')
in_mermaid = False
result = []
for line in lines:
if line.strip().startswith('```mermaid'):
in_mermaid = True
result.append(line)
elif line.strip() == '```' and in_mermaid:
in_mermaid = False
result.append(line)
elif in_mermaid:
# Fix <br> to <br/> in mermaid
# But be careful with quoted strings
fixed = line.replace('<br>', '<br/>')
result.append(fixed)
else:
result.append(line)
return '\n'.join(result)
def fix_html_entities(content: str) -> str: """Fix common HTML entities that cause rendering issues.""" # Replace with regular space content = content.replace(' ', ' ') # Replace ...; entities that might not render content = re.sub(r'\d+;', ' ', content) return content
def ensure_final_newline(content: str) -> str: """Ensure file ends with a newline.""" if not content.endswith('\n'): content += '\n' return content
def fix_file(file_path: Path) -> dict: """Fix all issues in a markdown file.""" try: with open(file_path, 'r', encoding='utf-8') as f: original = f.read() except Exception as e: return {'error': str(e), 'fixed': False}
content = original
changes = []
# Fix trailing whitespace
fixed = fix_trailing_whitespace(content)
if fixed != content:
changes.append('trailing_whitespace')
content = fixed
# Fix mermaid <br> tags
fixed = fix_mermaid_br_tags(content)
if fixed != content:
changes.append('mermaid_br_tags')
content = fixed
# Fix HTML entities
fixed = fix_html_entities(content)
if fixed != content:
changes.append('html_entities')
content = fixed
# Ensure final newline
fixed = ensure_final_newline(content)
if fixed != content:
changes.append('final_newline')
content = fixed
# Write back if changed
if content != original:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
return {'fixed': True, 'changes': changes}
return {'fixed': False, 'changes': []}
def main(): parser = argparse.ArgumentParser(description='Fix common markdown issues') parser.add_argument('path', help='File or directory to process') parser.add_argument('--dry-run', action='store_true', help='Show what would be fixed without making changes')
args = parser.parse_args()
target = Path(args.path)
if not target.exists():
print(f"Error: {target} does not exist")
sys.exit(1)
files_to_process = []
if target.is_file():
if target.suffix == '.md':
files_to_process.append(target)
else:
# Find all markdown files
exclude = ['.venv', '.git', 'node_modules', '__pycache__', 'context-storage']
for md_file in target.rglob('*.md'):
if any(excl in str(md_file) for excl in exclude):
continue
files_to_process.append(md_file)
print(f"Processing {len(files_to_process)} markdown files...")
fixed_count = 0
error_count = 0
for file_path in files_to_process:
result = fix_file(file_path)
if 'error' in result:
print(f"❌ {file_path}: {result['error']}")
error_count += 1
elif result['fixed']:
if args.dry_run:
print(f"🔧 {file_path}: Would fix {', '.join(result['changes'])}")
else:
print(f"✅ {file_path}: Fixed {', '.join(result['changes'])}")
fixed_count += 1
print(f"\nSummary: {fixed_count} files fixed, {error_count} errors")
if error_count > 0:
sys.exit(1)
if name == 'main': main()