v0.2.10-pre.002
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user