mirror of
https://github.com/nubenetes/awesome-kubernetes.git
synced 2026-07-12 18:00:37 +00:00
108 lines
4.6 KiB
Python
Executable File
108 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
def check_file(file_path):
|
|
errors = []
|
|
warnings = []
|
|
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
content = f.read()
|
|
lines = content.splitlines()
|
|
|
|
seen_urls = set()
|
|
|
|
for line_num, line in enumerate(lines, 1):
|
|
# 1. Check section titles (H2-H6) for Emojis, Special Characters, and Ampersands (Mandate 32)
|
|
if line.startswith("#"):
|
|
header_level = len(line) - len(line.lstrip('#'))
|
|
if 2 <= header_level <= 6:
|
|
title_text = line.lstrip('#').strip()
|
|
# Check for ampersand
|
|
if "&" in title_text:
|
|
errors.append(f"Line {line_num}: Title contains ampersand '&': '{title_text}' (replace with 'and')")
|
|
|
|
# Check for emojis or special characters
|
|
for char in title_text:
|
|
# Allow alphanumeric, spaces, hyphens, colons, parentheses, commas, periods, quotes
|
|
if ord(char) > 0x2000 and ord(char) not in (0x2013, 0x2014, 0x2018, 0x2019, 0x201c, 0x201d):
|
|
errors.append(f"Line {line_num}: Title contains emojis or special characters: '{char}' in '{title_text}'")
|
|
|
|
# 2. Check for Markdown link rules (Mandate 33)
|
|
# Match [ Link ](URL) - space at start or end of brackets
|
|
if re.search(r'\[\s+[^\]]*\]\(', line) or re.search(r'\[[^\]]*\s+\]\(', line):
|
|
errors.append(f"Line {line_num}: Link text contains leading or trailing spaces inside brackets: '{line.strip()}'")
|
|
|
|
# 3. Extract and validate URLs
|
|
links = re.findall(r'\[([^\]]+)\]\(([^)]+)\)', line)
|
|
for link_text, url in links:
|
|
url = url.strip()
|
|
if url.startswith("http://") or url.startswith("https://"):
|
|
if url.startswith("https:/") and not url.startswith("https://"):
|
|
errors.append(f"Line {line_num}: Corrupted protocol prefix: '{url}'")
|
|
elif url.startswith("http:/") and not url.startswith("http://"):
|
|
errors.append(f"Line {line_num}: Corrupted protocol prefix: '{url}'")
|
|
|
|
# Check for duplicates in this category file
|
|
if os.path.basename(file_path) not in ["index.md", "about.md"]:
|
|
# Normalize URL to check duplicate
|
|
clean_url = url.split("?")[0].split("#")[0].lower().rstrip('/')
|
|
if clean_url in seen_urls:
|
|
# Report as warning rather than blocking error
|
|
warnings.append(f"Line {line_num}: Duplicate URL found in this file: '{url}'")
|
|
else:
|
|
seen_urls.add(clean_url)
|
|
|
|
# Check year tag if present
|
|
match_year = re.search(r'\*\*\(([0-9]{4})\)\*\*', line)
|
|
if match_year:
|
|
year = int(match_year.group(1))
|
|
if not (1990 <= year <= 2030):
|
|
errors.append(f"Line {line_num}: Year tag '{year}' is outside reasonable bounds: '{line.strip()}'")
|
|
|
|
# Global multi-line check for link text line breaks
|
|
if re.search(r'\[[^\]]*\n[^\]]*\]\(', content):
|
|
errors.append("Global: Found a link with a line break inside the link text brackets.")
|
|
|
|
return errors, warnings
|
|
|
|
def main():
|
|
docs_dir = "docs"
|
|
if not os.path.exists(docs_dir):
|
|
print(f"Directory {docs_dir} not found.")
|
|
sys.exit(0)
|
|
|
|
total_errors = 0
|
|
total_warnings = 0
|
|
|
|
for root, dirs, files in os.walk(docs_dir):
|
|
if "images" in root or "static" in root:
|
|
continue
|
|
for file in files:
|
|
if file.endswith(".md"):
|
|
path = os.path.join(root, file)
|
|
errors, warnings = check_file(path)
|
|
if errors:
|
|
print(f"❌ {path}:")
|
|
for err in errors:
|
|
print(f" {err}")
|
|
total_errors += len(errors)
|
|
if warnings:
|
|
# By default do not flood output with duplicate warnings unless verbose
|
|
if "--verbose" in sys.argv:
|
|
print(f"⚠️ {path}:")
|
|
for warn in warnings:
|
|
print(f" {warn}")
|
|
total_warnings += len(warnings)
|
|
|
|
print(f"\nScan complete: Found {total_errors} errors and {total_warnings} warnings in markdown files.")
|
|
if total_errors > 0:
|
|
sys.exit(1)
|
|
else:
|
|
print("All Markdown files passed the schema check successfully!")
|
|
sys.exit(0)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|