v0.2.10-pre.002

This commit is contained in:
2026-08-25 10:29:16 +02:00
parent 7f567bc1bb
commit af807afff5
10 changed files with 667 additions and 59 deletions

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python3
# file: scripts/audit_markdown_tables.py
# version: 1
# version: 2
"""Validate KSP Markdown table formatting for explicitly supplied files or directories."""
"""Validate KSP Markdown tables and vertical spacing for explicitly supplied files or directories."""
from __future__ import annotations
@@ -12,6 +12,7 @@ import re
import sys
_SEPARATOR_CELL = re.compile(r"^:?-{3,}:?$")
_IGNORED_DIRECTORY_NAMES = frozenset({".git", ".idea", ".venv", "__pycache__", "dist", "node_modules", "target"})
def _markdown_files(paths: list[str]) -> list[pathlib.Path]:
@@ -19,7 +20,13 @@ def _markdown_files(paths: list[str]) -> list[pathlib.Path]:
for raw_path in paths:
path = pathlib.Path(raw_path)
if path.is_dir():
files.extend(sorted(candidate for candidate in path.rglob("*.md") if candidate.is_file()))
files.extend(
sorted(
candidate
for candidate in path.rglob("*.md")
if candidate.is_file() and not any(part in _IGNORED_DIRECTORY_NAMES for part in candidate.parts)
)
)
elif path.is_file() and path.suffix.lower() == ".md":
files.append(path)
else:
@@ -101,9 +108,47 @@ def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> lis
return errors
def _validate_blank_lines(path: pathlib.Path, lines: list[str]) -> list[str]:
errors: list[str] = []
fence_marker: str | None = None
blank_run_start: int | None = None
blank_run_length = 0
def flush_blank_run() -> None:
nonlocal blank_run_start, blank_run_length
if blank_run_start is not None and blank_run_length >= 2:
errors.append(
f"{path}:{blank_run_start}: {blank_run_length} consecutive blank lines are forbidden outside fenced code blocks; keep at most one"
)
blank_run_start = None
blank_run_length = 0
for line_number, line in enumerate(lines, start=1):
stripped = line.lstrip()
if stripped.startswith("```") or stripped.startswith("~~~"):
flush_blank_run()
marker = stripped[:3]
if fence_marker is None:
fence_marker = marker
elif marker == fence_marker:
fence_marker = None
continue
if fence_marker is not None:
continue
if line.strip() == "":
if blank_run_start is None:
blank_run_start = line_number
blank_run_length += 1
continue
flush_blank_run()
flush_blank_run()
return errors
def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
lines = path.read_text(encoding="utf-8").splitlines()
errors: list[str] = []
errors = _validate_blank_lines(path, lines)
table_count = 0
fence_marker: str | None = None
index = 0
@@ -135,7 +180,7 @@ def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
def main() -> int:
"""Audit Markdown tables in the explicitly selected scope."""
"""Audit KSP Markdown formatting in the explicitly selected scope."""
parser = argparse.ArgumentParser()
parser.add_argument("paths", nargs="+", help="Markdown files or directories to audit")