/** * The vault's own sense of itself — links, backlinks, tags, the graph — * and the markdown it is written in, which the browser renders with the * very same file. */ import { expect, test } from "bun:test"; // @ts-ignore — plain JS, shared with the browser. import { render } from "../static/md.js"; import { backlinks, excerpt, graph, headings, links, outgoing, relink, renderNote, search, tagCounts, tags, type VaultNote, } from "./vault.ts"; const note = (id: number, title: string, body: string, updated_at = `2026-10-0${id}`): VaultNote => ({ id, title, body, pinned: 0, updated_at, }); test("links and tags are found in prose, never in code", () => { const body = "See [[Alpha]], [[beta|B]] and [[Alpha#Part]].\n`[[Not]] #nope`\n```\n[[Fenced]] #fenced\n```\n#real and #nested/tag, not #123 or a#b"; expect(links(body)).toEqual(["Alpha", "beta"]); expect(tags(body)).toEqual(["real", "nested/tag"]); expect(headings("# One\ntext\n## Two ##\n```\n# not\n```")).toEqual([ { level: 1, text: "One", id: "one" }, { level: 2, text: "Two", id: "two" }, ]); }); test("backlinks, links out, tag counts and the graph agree", () => { const a = note(1, "Alpha", "to [[Beta]] and [[Missing]] #x"); const b = note(2, "Beta", "back to [[alpha]] #x #y"); const c = note(3, "Gamma", "to [[BETA]]"); const vault = [a, b, c]; expect(backlinks(b, vault).map((n) => n.id)).toEqual([1, 3]); expect(backlinks(c, vault)).toEqual([]); expect(outgoing(a, vault)).toEqual({ found: [b], missing: ["Missing"] }); expect(tagCounts(vault)).toEqual([ { tag: "x", count: 2 }, { tag: "y", count: 1 }, ]); const g = graph(vault); expect(g.edges).toEqual([ [1, 2], [3, 2], ]); expect(g.nodes.find((n) => n.id === 2)?.links).toBe(2); }); test("relink rewrites only links to the old title", () => { expect(relink("[[Old]] [[old|alias]] [[Old#h]] ![[Old]] [[Older]] Old", "Old", "New")).toBe( "[[New]] [[New|alias]] [[New#h]] ![[New]] [[Older]] Old", ); }); test("search ranks title matches first, then the most recent", () => { const vault = [note(1, "Plant", "water"), note(2, "Garden", "plant beds"), note(3, "Shed", "plant pots")]; expect(search(vault, "plant").map((h) => h.note.id)).toEqual([1, 3, 2]); expect(search(vault, "")).toEqual([]); expect(excerpt("# Head\n**bold** [[A|alias]] text")).toBe("Head bold alias text"); }); test("markdown renders the everyday core", () => { const html = render( "# Title\n\nSome **bold**, *em*, ~~gone~~, ==lit== and `code`.\n\n- one\n - nested\n- [x] done\n- [ ] todo\n\n1. first\n2. second\n\n> quoted\n\n---\n\n| a | b |\n|---|--:|\n| 1 | 2 |\n\n```js\nlet x = 1 < 2;\n```", ); for (const piece of [ '

Title

', "bold", "em", "gone", "lit", "code", "