103 lines
2.4 KiB
TypeScript
103 lines
2.4 KiB
TypeScript
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("<table>");
|
|
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(`
|
|
<script>alert("xss")</script>
|
|
|
|
[危险链接](javascript:alert("xss"))
|
|
`);
|
|
|
|
expect(result.bodyHtml).not.toContain("<script");
|
|
expect(result.bodyHtml).not.toMatch(/href=["']javascript:/u);
|
|
expect(result.bodyHtml).toContain("<script>");
|
|
});
|
|
|
|
it("为重复中文标题生成唯一锚点", () => {
|
|
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"');
|
|
});
|
|
});
|