import { describe, expect, test } from "bun:test"; const Markdown = Bun.markdown; // ============================================================================ // Bun.markdown.render() — callback-based string renderer // ============================================================================ describe("Bun.markdown.render", () => { test("returns a string", () => { const result = Markdown.render("# Hello\n", { heading: (children: string) => `

${children}

`, }); expect(typeof result).toBe("string"); }); test("without callbacks, children pass through unchanged", () => { const result = Markdown.render("Hello world\n"); expect(result).toBe("Hello world"); }); test("heading callback with level metadata", () => { const result = Markdown.render("# Hello\n", { heading: (children: string, { level }: any) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe("

Hello

"); }); test("heading levels 1-6", () => { for (let i = 1; i <= 6; i++) { const md = Buffer.alloc(i, "#").toString() + " Level\n"; const result = Markdown.render(md, { heading: (children: string, { level }: any) => `[h${level}:${children}]`, }); expect(result).toBe(`[h${i}:Level]`); } }); test("paragraph callback", () => { const result = Markdown.render("Hello world\n", { paragraph: (children: string) => `

${children}

`, }); expect(result).toBe("

Hello world

"); }); test("strong callback", () => { const result = Markdown.render("**bold**\n", { strong: (children: string) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe("bold"); }); test("emphasis callback", () => { const result = Markdown.render("*italic*\n", { emphasis: (children: string) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe("italic"); }); test("link callback with href metadata", () => { const result = Markdown.render("[click](https://example.com)\n", { link: (children: string, { href }: any) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe('click'); }); test("link callback with title metadata", () => { const result = Markdown.render('[click](https://example.com "My Title")\n', { link: (children: string, { href, title }: any) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe('click'); }); test("image callback with src metadata", () => { const result = Markdown.render("![alt text](image.png)\n", { image: (children: string, { src }: any) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe('alt text'); }); test("code block callback with language metadata", () => { const result = Markdown.render("```js\nconsole.log('hi');\n```\n", { code: (children: string, meta: any) => `
${children}
`, }); expect(result).toBe("
console.log('hi');\n
"); }); test("code block without language", () => { const result = Markdown.render("```\nplain code\n```\n", { code: (children: string, meta: any) => `
${children}
`, }); expect(result).toBe('
plain code\n
'); }); test("codespan callback", () => { const result = Markdown.render("`code`\n", { codespan: (children: string) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe("code"); }); test("hr callback", () => { const result = Markdown.render("---\n", { hr: () => "
", }); expect(result).toBe("
"); }); test("blockquote callback", () => { const result = Markdown.render("> quoted text\n", { blockquote: (children: string) => `
${children}
`, paragraph: (children: string) => `

${children}

`, }); expect(result).toBe("

quoted text

"); }); test("list callbacks (ordered)", () => { const result = Markdown.render("1. first\n2. second\n", { list: (children: string, { ordered, start }: any) => ordered ? `
    ${children}
` : ``, listItem: (children: string) => `
  • ${children}
  • `, }); expect(result).toBe('
    1. first
    2. second
    '); }); test("list callbacks (unordered)", () => { const result = Markdown.render("- a\n- b\n", { list: (children: string, { ordered }: any) => (ordered ? `
      ${children}
    ` : ``), listItem: (children: string) => `
  • ${children}
  • `, }); expect(result).toBe(""); }); test("ordered list with start number", () => { const result = Markdown.render("3. first\n4. second\n", { list: (children: string, { start }: any) => `
      ${children}
    `, listItem: (children: string) => `
  • ${children}
  • `, }); expect(result).toBe('
    1. first
    2. second
    '); }); test("strikethrough callback", () => { const result = Markdown.render("~~deleted~~\n", { strikethrough: (children: string) => `${children}`, paragraph: (children: string) => children, }); expect(result).toBe("deleted"); }); test("text callback", () => { const result = Markdown.render("Hello world\n", { text: (text: string) => text.toUpperCase(), paragraph: (children: string) => children, }); expect(result).toBe("HELLO WORLD"); }); test("returning null omits element", () => { const result = Markdown.render("# Title\n\n![logo](img.png)\n\nHello\n", { image: () => null, heading: (children: string) => children, paragraph: (children: string) => children + "\n", }); expect(result).toBe("Title\nHello\n"); }); test("returning undefined omits element", () => { const result = Markdown.render("# Title\n\nHello\n", { heading: () => undefined, paragraph: (children: string) => children, }); expect(result).toBe("Hello"); }); test("multiple callbacks combined", () => { const result = Markdown.render("# Title\n\nHello **world**\n", { heading: (children: string, { level }: any) => `${children}`, paragraph: (children: string) => `

    ${children}

    `, strong: (children: string) => `${children}`, }); expect(result).toBe('

    Title

    Hello world

    '); }); test("stripping all formatting", () => { const result = Markdown.render("# Hello **world**\n", { heading: (children: string) => children, paragraph: (children: string) => children, strong: (children: string) => children, emphasis: (children: string) => children, link: (children: string) => children, image: () => "", code: (children: string) => children, codespan: (children: string) => children, }); expect(result).toBe("Hello world"); }); test("ANSI terminal output", () => { const result = Markdown.render("# Hello\n\nThis is **bold** and *italic*\n", { heading: (children: string) => `\x1b[1;4m${children}\x1b[0m\n`, paragraph: (children: string) => children + "\n", strong: (children: string) => `\x1b[1m${children}\x1b[22m`, emphasis: (children: string) => `\x1b[3m${children}\x1b[23m`, }); expect(result).toBe("\x1b[1;4mHello\x1b[0m\nThis is \x1b[1mbold\x1b[22m and \x1b[3mitalic\x1b[23m\n"); }); test("parser options work alongside callbacks", () => { const result = Markdown.render( "Visit www.example.com\n", { link: (children: string, { href }: any) => `[${children}](${href})`, paragraph: (children: string) => children, }, { autolinks: true }, ); expect(result).toContain("[www.example.com]"); }); test("headings option provides id in heading meta", () => { const result = Markdown.render( "## Hello World\n", { heading: (children: string, { level, id }: any) => `${children}`, }, { headings: { ids: true } }, ); expect(result).toBe('

    Hello World

    '); }); test("table callbacks", () => { const result = Markdown.render("| A | B |\n|---|---|\n| 1 | 2 |\n", { table: (children: string) => `${children}
    `, thead: (children: string) => `${children}`, tbody: (children: string) => `${children}`, tr: (children: string) => `${children}`, th: (children: string) => `${children}`, td: (children: string) => `${children}`, }); expect(result).toContain(""); expect(result).toContain(""); expect(result).toContain(""); }); test("entities are decoded", () => { const result = Markdown.render("&\n", { paragraph: (children: string) => children, }); expect(result).toBe("&"); }); });
    A1