import { describe, expect, it } from "vitest"; import { renderMarkdown } from "../src/render-markdown.js"; describe("renderMarkdown", () => { it("渲染常用 Markdown 扩展并识别能力", () => { const result = renderMarkdown(` # 示例文档 | 名称 | 状态 | | --- | --- | | PDF | 可用 | - [x] 已完成 - [ ] 待处理 \`\`\`ts const answer = 42; \`\`\` 脚注引用[^note]。 [^note]: 脚注正文。 `); expect(result.articleHtml).toContain('id="write"'); expect(result.bodyHtml).toContain(""); expect(result.bodyHtml).toContain("md-task-list-item"); expect(result.bodyHtml).toContain("hljs-keyword"); expect(result.bodyHtml).toContain("footnote"); expect(result.metadata.title).toBe("示例文档"); expect(result.features).toEqual( expect.arrayContaining(["code", "table", "task-list", "footnote"]) ); }); it("读取并规范化 Front Matter 元数据", () => { const result = renderMarkdown(`--- title: 项目报告 author: 张三 subject: 技术方案 keywords: - Markdown - PDF lang: zh-CN --- # 不作为标题 `); expect(result.metadata).toEqual({ title: "项目报告", author: "张三", subject: "技术方案", keywords: ["Markdown", "PDF"], language: "zh-CN" }); }); it("服务端渲染公式并保留 Mermaid 安全占位", () => { const result = renderMarkdown(` 内联公式 $E=mc^2$。 \`\`\`mermaid flowchart LR A[开始] --> B[结束] \`\`\` `); expect(result.bodyHtml).toContain("katex"); expect(result.bodyHtml).toContain('class="mermaid"'); expect(result.bodyHtml).toContain("data-mermaid-pending"); expect(result.features).toEqual( expect.arrayContaining(["katex", "mermaid"]) ); }); it("阻止原始 HTML 和危险链接形成可执行内容", () => { const result = renderMarkdown(` [危险链接](javascript:alert("xss")) `); expect(result.bodyHtml).not.toContain(" { const result = renderMarkdown(` # 章节 ## 章节 ## 章节 `); expect(result.bodyHtml).toContain('id="%E7%AB%A0%E8%8A%82"'); expect(result.bodyHtml).toContain('id="%E7%AB%A0%E8%8A%82-2"'); expect(result.bodyHtml).toContain('id="%E7%AB%A0%E8%8A%82-3"'); }); });