import assert from "node:assert/strict"; import { describe, it } from "vitest"; import { type FrontmatterMap, MarkdownDocumentError, parseFrontmatter, } from "../markdown.ts"; const rich = `--- id: PX-SPEC-001 type: spec title: Rich documents owners: [human, the-system] review: approved: 2026-07-15 flags: [visual, editable] --- # Rich documents Body after frontmatter stays unparsed. `; const entry = (frontmatter: FrontmatterMap, key: string) => frontmatter.get(key); describe("frontmatter parsing", () => { it("preserves frontmatter order and shapes", () => { const frontmatter = parseFrontmatter(rich); assert.deepEqual( [...frontmatter.keys()], ["id", "type", "title", "owners", "review"], ); assert.deepEqual(entry(frontmatter, "owners"), ["human", "the-system"]); assert.deepEqual( entry(frontmatter, "review"), new Map([ ["approved", "2026-07-15"], ["flags", ["visual", "editable"]], ]), ); }); it("accepts fences with trailing spaces or tabs", () => { assert.equal(entry(parseFrontmatter("--- \nid: A\n---\t\n"), "id"), "A"); }); it("accepts CRLF and CR line endings", () => { assert.equal(entry(parseFrontmatter("---\r\nid: A\r\n---\r\n"), "id"), "A"); assert.equal(entry(parseFrontmatter("---\rid: A\r---\r"), "id"), "A"); }); it("drops a byte order mark before the opening fence", () => { assert.equal(entry(parseFrontmatter("\ufeff---\nid: A\n---\n"), "id"), "A"); }); it("keeps lone carriage returns inside the value literal", () => { const frontmatter = parseFrontmatter("---\r\n \rk1: v1\r\n---\n"); assert.deepEqual([...frontmatter.keys()], ["\rk1"]); }); it("strips exactly one trailing line ending from the value", () => { const frontmatter = parseFrontmatter("---\nkey: |\n l1\n l2\n\n---\n"); assert.equal(entry(frontmatter, "key"), "l1\nl2\n"); }); it("rejects thematic breaks and indented or unclosed fences", () => { for (const source of [ "----\nid: A\n----\n", " ---\nid: A\n---\n", "\n---\nid: A\n---\n", "---\nid: A", "---id: A\n---\n", ]) assert.throws( () => parseFrontmatter(source), (error: unknown) => error instanceof MarkdownDocumentError && error.code === "frontmatter.missing", source, ); }); it("treats a dotted line as content, not a closing fence", () => { assert.equal(entry(parseFrontmatter("---\nid: A\n...\n---\n"), "id"), "A"); }); it("keeps fence-like lines inside the value instead of closing", () => { assert.throws( () => parseFrontmatter("---\nid: A\n---x\n---\n"), (error: unknown) => error instanceof MarkdownDocumentError && error.code === "frontmatter.invalid" && error.message.includes("---x"), ); }); it.each([ ["duplicate", "---\nid: A\nid: B\n---\n", "frontmatter.invalid"], ["alias", "---\na: &a [1]\nb: *a\n---\n", "frontmatter.unsupported"], ["empty", "---\n---\n", "frontmatter.shape"], ])("rejects %s frontmatter", (_name, source, code) => { assert.throws( () => parseFrontmatter(source), (error: unknown) => error instanceof MarkdownDocumentError && error.code === code, ); }); });