diff --git a/scripts/parse_validate_notes.py b/scripts/parse_validate_notes.py new file mode 100644 index 0000000..1fc5f66 --- /dev/null +++ b/scripts/parse_validate_notes.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +from __future__ import annotations +import argparse +import os +import sys +import glob +from jsonschema import ValidationError +from app.core.parser import read_markdown, validate_required_frontmatter, normalize_frontmatter +from app.core.note_payload import make_note_payload +from app.core.validate_note import validate_note_payload + +def iter_md_files(root: str, include: str, exclude: list[str]) -> list[str]: + # include z.B. "**/*.md" + all_files = glob.glob(os.path.join(root, include), recursive=True) + def is_excluded(p: str) -> bool: + p_norm = p.replace("\\", "/") + return any(x in p_norm for x in exclude) + return [p for p in all_files if p.lower().endswith(".md") and not is_excluded(p)] + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--vault", required=True, help="Pfad zum Obsidian Vault") + ap.add_argument("--include", default="**/*.md") + ap.add_argument("--exclude", nargs="*", default=["/.obsidian/", "/_imported/"]) + args = ap.parse_args() + + root = os.path.abspath(args.vault) + files = iter_md_files(root, args.include, args.exclude) + + if not files: + print("Keine Markdown-Dateien gefunden.", file=sys.stderr) + sys.exit(2) + + ok, failed = 0, 0 + for path in files: + try: + parsed = read_markdown(path) + fm = normalize_frontmatter(parsed.frontmatter) + validate_required_frontmatter(fm) + # Note-Payload gemäß note.schema.json validieren + payload = make_note_payload(parsed, vault_root=root) + validate_note_payload(payload) + ok += 1 + except (ValidationError, ValueError) as e: + failed += 1 + print(f"❌ {os.path.relpath(path, root)} :: {e}", file=sys.stderr) + + print(f"✅ Valid: {ok} | ❌ Invalid: {failed}") + if failed: + sys.exit(1) + +if __name__ == "__main__": + main()