import {describe, expect, it} from "bun:test"; import {classifyLines} from "../src/markdownStructure"; describe("classifyLines – plain content", () => { it("classifies all lines as content when there is no frontmatter or code", () => { const input = "# Title\n\n- [ ] open\n- text\n"; expect(classifyLines(input)).toEqual([ "content", "content", "content", "content", "content", ]); }); }); describe("classifyLines – fenced code blocks", () => { it("classifies backtick-fenced lines as code", () => { const input = ["before", "```", "- [ ] not a task", "```", "after"].join("\n"); expect(classifyLines(input)).toEqual(["content", "code", "code", "code", "content"]); }); it("classifies tilde-fenced lines as code", () => { const input = ["before", "~~~", "- [ ] not a task", "~~~", "after"].join("\n"); expect(classifyLines(input)).toEqual(["content", "code", "code", "code", "content"]); }); it("supports info strings on the opening fence", () => { const input = ["```markdown", "- [ ] not a task", "```"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code"]); }); it("does not close on a shorter fence", () => { const input = ["````", "```", "still in code", "````"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code", "code"]); }); it("does not treat tilde and backtick fences as matching", () => { const input = ["```", "~~~", "still code"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code"]); }); it("treats a closing fence with trailing whitespace as a closer", () => { const input = ["```", "x", "``` ", "after"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code", "content"]); }); it("does not treat a fence with info string as a closer", () => { const input = ["```", "x", "``` not-a-closer", "still", "```"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code", "code", "code"]); }); it("permits up to 3 spaces of indentation on the fence", () => { const input = [" ```", "- [ ] not a task", " ```", "after"].join("\n"); expect(classifyLines(input)).toEqual(["code", "code", "code", "content"]); }); }); describe("classifyLines – frontmatter", () => { it("treats opening --- only at the very first line", () => { const input = ["---", "Pending tasks: true", "---", "- [ ] open"].join("\n"); expect(classifyLines(input)).toEqual([ "frontmatter", "frontmatter", "frontmatter", "content", ]); }); it("does not treat a --- elsewhere as frontmatter", () => { const input = ["# Title", "---", "- [ ] open"].join("\n"); expect(classifyLines(input)).toEqual(["content", "content", "content"]); }); it("supports the YAML ... terminator", () => { const input = ["---", "key: value", "...", "- [ ] open"].join("\n"); expect(classifyLines(input)).toEqual([ "frontmatter", "frontmatter", "frontmatter", "content", ]); }); }); describe("classifyLines – combined", () => { it("handles frontmatter followed by content with a code block", () => { const input = [ "---", "foo: bar", "---", "- [ ] real task", "```", "- [ ] not a task", "```", "- [ ] another real task", ].join("\n"); expect(classifyLines(input)).toEqual([ "frontmatter", "frontmatter", "frontmatter", "content", "code", "code", "code", "content", ]); }); });