scripts-fix-md025-frontmatter-config
#!/usr/bin/env python3 """
title: "Fix Md025 Frontmatter Config" component_type: script version: "1.0.0" audience: contributor status: stable summary: "CODITECT Markdown Quality System Copyright © 2025 AZ1.AI INC - All Rights Reserved" keywords: ['config', 'fix', 'frontmatter', 'md025'] tokens: ~500 created: 2025-12-22 updated: 2025-12-22 script_name: "fix-md025-frontmatter-config.py" language: python executable: true usage: "python3 scripts/fix-md025-frontmatter-config.py [options]" python_version: "3.10+" dependencies: [] modifies_files: false network_access: false requires_auth: false
CODITECT Markdown Quality System Copyright © 2025 AZ1.AI INC - All Rights Reserved
This software is proprietary and confidential. Unauthorized copying, distribution, or use is strictly prohibited.
CODITECT owns all intellectual property rights to this implementation.
MD025 False Positive Fix - Configuration Update
This script fixes MD025 "Multiple top-level headings" false positives caused by
YAML frontmatter title: fields being treated as H1 headings.
The fix updates .markdownlint.json to set front_matter_title: "" which tells
markdownlint to ignore the YAML title field when checking for multiple H1s.
Usage: python3 fix-md025-frontmatter-config.py [directory] python3 fix-md025-frontmatter-config.py --dry-run [directory]
Note: This is a CONFIGURATION fix, not a content fix. For files with actual duplicate H1 headings, use fix-md025-multiple-top-headings.py instead. """
import json import argparse from pathlib import Path from typing import Optional
def find_markdownlint_config(start_path: Path) -> Optional[Path]: """Find .markdownlint.json in the given directory or parents.""" current = start_path.resolve()
# Search in current directory first
if current.is_file():
current = current.parent
# Check current directory
config_path = current / ".markdownlint.json"
if config_path.exists():
return config_path
# Also check for .markdownlint.jsonc
config_path = current / ".markdownlint.jsonc"
if config_path.exists():
return config_path
return None
def update_config(config_path: Path, dry_run: bool = False) -> bool: """Update .markdownlint.json to fix MD025 false positives.""" try: # Read existing config with open(config_path, 'r', encoding='utf-8') as f: content = f.read()
# Parse JSON (handle comments if present)
try:
config = json.loads(content)
except json.JSONDecodeError:
# Try removing comments (simple approach)
import re
clean_content = re.sub(r'//.*$', '', content, flags=re.MULTILINE)
config = json.loads(clean_content)
# Check if MD025 already configured correctly
if "MD025" in config:
if isinstance(config["MD025"], dict):
if config["MD025"].get("front_matter_title") == "":
print(f"✓ MD025 front_matter_title already configured in {config_path}")
return False
else:
# Update existing MD025 config
config["MD025"]["front_matter_title"] = ""
elif config["MD025"] is False:
print(f"⚠ MD025 is disabled entirely in {config_path} - no action needed")
return False
else:
# Replace with dict config
config["MD025"] = {"front_matter_title": ""}
else:
# Add MD025 config
config["MD025"] = {"front_matter_title": ""}
if dry_run:
print(f"[DRY RUN] Would update {config_path}")
print(f" Adding: \"MD025\": {{\"front_matter_title\": \"\"}}")
return True
# Write updated config
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2)
f.write('\n')
print(f"✓ Updated {config_path}")
print(f" Added: \"MD025\": {{\"front_matter_title\": \"\"}}")
return True
except Exception as e:
print(f"✗ Error updating {config_path}: {e}")
return False
def create_config(target_dir: Path, dry_run: bool = False) -> bool: """Create a new .markdownlint.json with MD025 fix.""" config_path = target_dir / ".markdownlint.json"
config = {
"default": True,
"MD025": {
"front_matter_title": ""
}
}
if dry_run:
print(f"[DRY RUN] Would create {config_path}")
print(f" With MD025 front_matter_title fix")
return True
try:
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2)
f.write('\n')
print(f"✓ Created {config_path}")
print(f" With: \"MD025\": {{\"front_matter_title\": \"\"}}")
return True
except Exception as e:
print(f"✗ Error creating {config_path}: {e}")
return False
def main(): parser = argparse.ArgumentParser( description='Fix MD025 false positives from YAML frontmatter titles', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" This script updates .markdownlint.json to ignore YAML frontmatter titles when checking for multiple top-level headings (MD025).
Problem: Files with YAML frontmatter like:
title: "My Document"
My Document
trigger MD025 because markdownlint treats the YAML title as an H1 heading.
Solution: Configure MD025 with front_matter_title: "" to disable this behavior.
For actual duplicate H1s, use fix-md025-multiple-top-headings.py instead. """ ) parser.add_argument('path', nargs='?', default='.', help='Directory to update config in (default: current)') parser.add_argument('--dry-run', action='store_true', help='Show what would be changed without modifying files') parser.add_argument('--create', action='store_true', help='Create .markdownlint.json if it does not exist')
args = parser.parse_args()
target_path = Path(args.path).resolve()
if not target_path.exists():
print(f"Error: Path does not exist: {target_path}")
return 1
if target_path.is_file():
target_path = target_path.parent
# Find existing config
config_path = find_markdownlint_config(target_path)
if config_path:
success = update_config(config_path, args.dry_run)
elif args.create:
success = create_config(target_path, args.dry_run)
else:
print(f"No .markdownlint.json found in {target_path}")
print("Use --create to create one, or manually create .markdownlint.json")
return 1
if success:
print("\nMD025 false positive fix applied.")
print("Re-run markdownlint to verify YAML frontmatter titles are now ignored.")
return 0
else:
return 1
if name == 'main': exit(main())