d6d7dd82f6
Create @docmost/prosemirror-markdown — the single framework-free ProseMirror<-> Markdown converter + schema mirror that git-sync and mcp will both consume, ending the three-hand-synced-copies drift (#293). This step only CREATES the package (no consumer yet; git-sync untouched); the switch of git-sync and mcp onto it, plus the canonical format decisions, come in later commits of this PR. - packages/prosemirror-markdown/src/lib/: the 8 converter-core files copied VERBATIM from packages/git-sync/src/lib (docmost-schema, markdown-converter, markdown-to-prosemirror, canonicalize, markdown-document, node-ops, page-file, index). Confirmed byte-identical — no behavioral drift introduced. - src/index.ts barrel; package.json (@tiptap/* + jsdom/marked/zod, editor-ext workspace devDep for the contract test); tsconfig/vitest configs. - 24 converter-core test files + fixtures copied (engine-coupled layout/ redteam-layout-title tests correctly excluded — they import ../src/engine). - pnpm-lock importer added; build/ gitignored (CI-built). Verified (clean checkout, no network): pnpm --frozen-lockfile EXIT 0; tsc EXIT 0; vitest 23 files, 443 passed | 1 expected-fail (the same image-diagrams known-limitation carried from git-sync) — faithful extraction. git-sync untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { parsePageFile, serializePageFile } from "../src/lib/page-file";
|
|
|
|
describe("page-file thin format", () => {
|
|
it("round-trips id frontmatter + clean body", () => {
|
|
const text = serializePageFile("019ef6fc-2638", "# Hello\n\nbody text");
|
|
expect(text.startsWith("---\ngitmost_id: 019ef6fc-2638\n---\n")).toBe(true);
|
|
const { id, body } = parsePageFile(text);
|
|
expect(id).toBe("019ef6fc-2638");
|
|
expect(body).toBe("# Hello\n\nbody text");
|
|
});
|
|
|
|
it("serialization is deterministic (byte-identical for the same input)", () => {
|
|
expect(serializePageFile("p", "x")).toBe(serializePageFile("p", "x"));
|
|
});
|
|
|
|
it("reads id from frontmatter with quotes / extra fields", () => {
|
|
expect(parsePageFile('---\ngitmost_id: "abc"\ntitle: ignored\n---\nbody').id).toBe("abc");
|
|
expect(parsePageFile("---\ngitmost_id: 'xyz'\n---\nbody").id).toBe("xyz");
|
|
});
|
|
|
|
|
|
it("ADOPT: a plain hand-written file has no id and keeps its whole body", () => {
|
|
const { id, body } = parsePageFile("# Just a note\n\nwritten in Obsidian");
|
|
expect(id).toBeNull();
|
|
expect(body).toBe("# Just a note\n\nwritten in Obsidian");
|
|
});
|
|
|
|
it("tolerates empty / whitespace input", () => {
|
|
expect(parsePageFile("").id).toBeNull();
|
|
expect(parsePageFile(" \n ").body).toBe("");
|
|
});
|
|
});
|