import re from pathlib import Path from app.command_target import extract_command_target, parse_kv_arg from app.vaults import vault_root_for_target DATE_ONLY_RE = re.compile(r"^\d{4}-\d{2}-\d{2}T?$") def arg_value(args:list[str], name:str) -> str|None: for arg in args: parsed = parse_kv_arg(arg) if parsed and parsed[0] == name and parsed[1]: return parsed[1] return None def normalize_property_datetime_args(args:list[str]) -> list[str]: target = extract_command_target(args) if target.command != "property:set" or arg_value(args, "type") != "datetime": return args value = arg_value(args, "value") if not value or not DATE_ONLY_RE.match(value): return args normalized_value = f"{value.rstrip('T')}T00:00:00" return [f"value={normalized_value}" if parse_kv_arg(arg) == ("value", value) else arg for arg in args] def vault_note_path(vault_root:Path, path:str) -> Path: note_path = (vault_root / path).resolve() try: note_path.relative_to(vault_root.resolve()) except ValueError as exc: raise PermissionError(f"path escapes vault: {path}") from exc return note_path def create_missing_property_file(args:list[str], cwd:Path) -> None: target = extract_command_target(args) if target.command != "property:set": return path = arg_value(args, "path") if not path: return note_path = vault_note_path(vault_root_for_target(target, cwd), path) if note_path.exists(): return note_path.parent.mkdir(parents=True, exist_ok=True) note_path.write_text("", encoding="utf-8") def prepare_property_args(args:list[str], cwd:Path) -> list[str]: args = normalize_property_datetime_args(args) create_missing_property_file(args, cwd) return args