from __future__ import annotations from flask import Blueprint, abort, redirect, render_template, request, url_for, jsonify, current_app from app.services.notes_fs import create_note, list_notes, load_note_by_id, update_note_body from app.services.renderer import render_markdown from app.services.vault import Vault import frontmatter import os bp = Blueprint("notes", __name__, url_prefix="/notes") @bp.get("/") def notes_index(): notes = list_notes() return render_template("notes/list.html", notes=notes) @bp.get("/new") def notes_new(): return render_template("notes/new.html") @bp.post("/") def notes_create(): title = (request.form.get("title") or "").strip() body = (request.form.get("body") or "").strip() tags_raw = (request.form.get("tags") or "").strip() tags = [t.strip() for t in tags_raw.split(",") if t.strip()] if tags_raw else [] if not title: return render_template("notes/new.html", error="Title is required", title=title, body=body, tags_raw=tags_raw), 400 note = create_note(title=title, body=body, tags=tags) return redirect(url_for("notes.notes_view", note_id=note.id)) @bp.get("/") def notes_view(note_id: str): note = load_note_by_id(note_id) if not note: abort(404) all_notes = list_notes() rendered = render_markdown(note.body or "", all_notes=all_notes) return render_template( "notes/view.html", note=note, rendered_html=rendered["html"], unresolved_wikilinks=rendered["unresolved_wikilinks"], outbound_note_ids=rendered["outbound_note_ids"], ) @bp.post("//body") def notes_update_body(note_id: str): new_body = request.form.get("body") or "" note = update_note_body(note_id, new_body) if not note: abort(404) return redirect(url_for("notes.notes_view", note_id=note.id)) @bp.get("/_debug/ids") def notes_debug_ids(): notes = list_notes() return jsonify( notes=[ {"id": n.id, "title": n.title, "path": n.rel_path} for n in notes] ) @bp.get("/_debug/scan") def notes_debug_scan(): vault_path = current_app.config.get("KB_VAULT_PATH") v = Vault(vault_path) v.ensure_structure() notes_dir = v.paths.notes exists = os.path.isdir(notes_dir) ls_notes = [] if exists: try: ls_notes = sorted(os.listdir(notes_dir)) except Exception as e: ls_notes = [f""] discovered = list(v.iter_markdown_files()) probe = [] for p in discovered: try: with open(p, "r", encoding="utf-8", errors="replace") as f: post = frontmatter.loads(f.read()) meta = post.metadata or {} probe.append({ "path": p, "ok": True, "id": meta.get("id"), "title": meta.get("title"), }) except Exception as e: probe.append({ "path": p, "ok": False, "error": str(e), }) return jsonify({ "vault": vault_path, "notes_dir": notes_dir, "notes_dir_exists": exists, "notes_dir_list": ls_notes, "discovered_md_files": discovered, "probe": probe, })