"""命令行入口。 用法: md-clean single [-o output.md] [--diff] [--rules rules.yaml] md-clean batch [-o outdir] [--pattern "*.md"] [--report report.json] """ from __future__ import annotations import argparse import json import sys from pathlib import Path from typing import List, Optional from cleaner.cleaner import MarkdownCleaner from cleaner.rules import load_rules def _build(path: Optional[Path]) -> MarkdownCleaner: return MarkdownCleaner(rules=load_rules(path)) def cmd_single(args: argparse.Namespace) -> int: cleaner = _build(args.rules) src = Path(args.input) raw = src.read_text(encoding="utf-8") result = cleaner.clean_text(raw) if args.output: Path(args.output).parent.mkdir(parents=True, exist_ok=True) Path(args.output).write_text(result.text, encoding="utf-8") print(f"已写入 {args.output}") if args.diff: print(MarkdownCleaner.diff(raw, result.text)) print(json.dumps(result.stats, ensure_ascii=False, indent=2)) return 0 def cmd_batch(args: argparse.Namespace) -> int: cleaner = _build(args.rules) src_dir = Path(args.directory) files = sorted(p for p in src_dir.rglob(args.pattern) if p.is_file()) if not files: print(f"在 {src_dir} 下未找到匹配 {args.pattern} 的文件", file=sys.stderr) return 1 out_dir = Path(args.output) if args.output else src_dir.parent / (src_dir.name + "_cleaned") report = [] for f in files: rel = f.relative_to(src_dir) dst = out_dir / rel result = cleaner.clean_file(f, dst) report.append({"file": str(rel), "stats": result.stats}) hits = result.total_hits print(f"[ok] {rel} 命中 {hits} 处") if args.report: Path(args.report).parent.mkdir(parents=True, exist_ok=True) Path(args.report).write_text( json.dumps({"files": report}, ensure_ascii=False, indent=2), encoding="utf-8" ) print(f"报告已写入 {args.report}") print(f"共清洗 {len(files)} 个文件 → {out_dir}") return 0 def main(argv: Optional[List[str]] = None) -> int: parser = argparse.ArgumentParser(prog="md-clean", description="政务文档 Markdown 清洗工具") sub = parser.add_subparsers(dest="command", required=True) p1 = sub.add_parser("single", help="清洗单个文件") p1.add_argument("input", help="输入 .md 文件") p1.add_argument("-o", "--output", help="输出路径(缺省打印统计不写文件)") p1.add_argument("--diff", action="store_true", help="打印 unified diff") p1.add_argument("--rules", type=Path, help="规则 YAML 路径") p2 = sub.add_parser("batch", help="批量清洗目录(递归)") p2.add_argument("directory", help="输入目录") p2.add_argument("-o", "--output", help="输出目录(缺省 _cleaned)") p2.add_argument("--pattern", default="*.md", help="文件 glob(默认 *.md)") p2.add_argument("--report", help="清洗报告 JSON 输出路径") p2.add_argument("--rules", type=Path, help="规则 YAML 路径") args = parser.parse_args(argv) if args.command == "single": return cmd_single(args) return cmd_batch(args) if __name__ == "__main__": sys.exit(main())