import { describe, expect, test } from "bun:test"; import { front, inline, render, sheet, slug } from "./md.ts"; const math = (tex: string, display: boolean) => `${tex}`; const link = (url: string) => (/^(https?:|#|\/)/.test(url) ? url : `/L/${url}`); describe("md", () => { test("headings carry the slug of their text and repeat with a counter", () => { const html = render("## Base $\\pi$ and *em*\n\n## Base $\\pi$ and *em*", { math }); expect(html).toContain(`

`); expect(html).toContain(`

`); }); test("a lone image line is a figure with an inline caption, an inline image stays an image", () => { expect(render("![the *walk*](walks-fig)", { link })).toBe('
the walk
the walk
'); expect(render("see ![walk](walks-fig) here", { link })).toBe('

see walk here

'); }); test("the widget line mounts a view through the hook and is a figure without one", () => { const widget = (name: string, view: string, caption: string) => `${caption}`; expect(render("![Life](demos/life/grid)", { widget })).toBe("Life"); expect(render("![Life](demos/life/grid)", { link })).toContain(' { expect(render("$aa and x^2

"); expect(render("$$x^2$$", { math })).toBe("x^2"); expect(render("$$\ny\n$$", { math })).toBe("y"); expect(render("$F = \\\\{0\\\\}$", { math })).toBe("

F = \\{0\\}

"); expect(render("$5 and $10")).toBe("

$5 and $10

"); }); test("a table is wrapped, aligned by class and one row per line", () => { const html = render("| a | b | c |\n|:--|:-:|--:|\n| 1 | 2 | 3 |"); expect(html).toBe('
\n\n
abc
123
'); }); test("an asterisk between two word characters is literal, around words it is emphasis, in code it is untouched", () => { expect(render("3*n*(n+1) and *\"2*20^n + 4*8^n\"* and `a*b*c`")).toBe('

3*n*(n+1) and "2*20^n + 4*8^n" and a*b*c

'); }); test("every link and bare url goes through the resolver", () => { expect(render("[a](x.md) and https://oeis.org/A1", { link })).toBe('

a and https://oeis.org/A1

'); }); test("raw html is shown as text", () => { expect(render("nx")).toBe("

n<m and <b>x</b>

"); }); test("lists are tight, so a dated claim line starts its item", () => { expect(render("- 2026-09-19 [Proved] one\n- two\n\n1. a\n2. b")).toBe("
    \n
  • 2026-09-19 [Proved] one
  • \n
  • two
  • \n
\n
    \n
  1. a
  2. \n
  3. b
  4. \n
"); }); test("inline drops the paragraph", () => { expect(inline("a **b** [c](d)", { link })).toBe('a b c'); }); test("sheet splits the title, the lead and the body", () => { const doc = sheet("# Hi *there*\n\nLead with [a](b).\n\n## Next\n\n- x", link); expect(doc).toEqual({ title: "Hi there", lead: 'Lead with a.', text: "Lead with a.", body: '

Next

\n
    \n
  • x
  • \n
' }); expect(sheet("Just prose.").title).toBe(""); }); test("front matter is key colon value lines", () => { expect(front("---\ntitle: T\nlead: L\n---\nbody")).toEqual({ data: { title: "T", lead: "L" }, body: "body" }); expect(front("body").data).toEqual({}); }); });