import { describe, it, expect } from "vitest";
import { parseMarkdownIntoBlocks } from "./parse-blocks";
describe("parseMarkdownIntoBlocks", () => {
describe("basic parsing", () => {
it("parses simple paragraph", () => {
const blocks = parseMarkdownIntoBlocks("Hello world");
expect(blocks).toHaveLength(1);
expect(blocks[0]).toBe("Hello world");
});
it("parses multiple paragraphs", () => {
const blocks = parseMarkdownIntoBlocks("First paragraph\n\nSecond paragraph");
// Includes space token between paragraphs
expect(blocks.length).toBeGreaterThanOrEqual(2);
expect(blocks.join("")).toContain("First paragraph");
expect(blocks.join("")).toContain("Second paragraph");
});
it("parses headings", () => {
const blocks = parseMarkdownIntoBlocks("# Heading\n\nParagraph");
expect(blocks).toHaveLength(2);
expect(blocks[0]).toContain("# Heading");
});
});
describe("code blocks", () => {
it("keeps code block as single block", () => {
const markdown = "```js\nconst x = 1;\nconst y = 2;\n```";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
expect(blocks[0]).toBe(markdown);
});
it("separates code blocks from text", () => {
const markdown = "Text before\n\n```js\ncode\n```\n\nText after";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks.length).toBeGreaterThan(1);
});
});
describe("math blocks", () => {
it("merges math blocks correctly", () => {
const markdown = "$$\nx^2 + y^2 = z^2\n$$";
const blocks = parseMarkdownIntoBlocks(markdown);
// Math blocks may be merged or kept separate depending on tokenization
const combined = blocks.join("");
expect(combined).toContain("$$");
expect(combined).toContain("x^2");
});
it("merges unclosed math with closing $$", () => {
const markdown = "$$\nmath content\n\n$$";
const blocks = parseMarkdownIntoBlocks(markdown);
// Should merge to keep math block together
const combined = blocks.join("");
expect(combined).toContain("math content");
});
});
describe("HTML blocks", () => {
it("merges HTML blocks with content", () => {
const markdown = "
\nContent inside div\n
";
const blocks = parseMarkdownIntoBlocks(markdown);
const combined = blocks.join("");
expect(combined).toContain("");
expect(combined).toContain("
");
});
it("handles self-closing tags", () => {
const markdown = "
\n\nParagraph";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks.length).toBeGreaterThanOrEqual(1);
});
});
describe("footnotes", () => {
it("returns entire document as single block when footnotes present", () => {
const markdown = "Text with footnote[^1]\n\n[^1]: Footnote definition";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
expect(blocks[0]).toBe(markdown);
});
it("returns entire document for footnote references", () => {
const markdown = "See reference[^note] for details.";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
});
});
describe("lists", () => {
it("parses unordered lists", () => {
const markdown = "- Item 1\n- Item 2\n- Item 3";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
expect(blocks[0]).toContain("Item 1");
});
it("parses ordered lists", () => {
const markdown = "1. First\n2. Second\n3. Third";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
});
});
describe("blockquotes", () => {
it("parses blockquotes", () => {
const markdown = "> This is a quote\n> Continued";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
expect(blocks[0]).toContain(">");
});
});
describe("tables", () => {
it("parses GFM tables", () => {
const markdown = "| Header 1 | Header 2 |\n|----------|----------|\n| Cell 1 | Cell 2 |";
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks).toHaveLength(1);
expect(blocks[0]).toContain("Header 1");
});
});
describe("edge cases", () => {
it("handles empty string", () => {
const blocks = parseMarkdownIntoBlocks("");
expect(blocks).toEqual([]);
});
it("handles whitespace only", () => {
const blocks = parseMarkdownIntoBlocks(" \n\n ");
// Should produce space tokens
expect(Array.isArray(blocks)).toBe(true);
});
it("handles mixed content", () => {
const markdown = `# Heading
Paragraph text with **bold** and *italic*.
\`\`\`python
def hello():
print("world")
\`\`\`
- List item 1
- List item 2
> A quote
| Col 1 | Col 2 |
|-------|-------|
| A | B |`;
const blocks = parseMarkdownIntoBlocks(markdown);
expect(blocks.length).toBeGreaterThan(0);
const combined = blocks.join("");
expect(combined).toContain("# Heading");
expect(combined).toContain("**bold**");
expect(combined).toContain("def hello()");
});
});
});