Files
UHD_Media_Tool/apps/web/app/components/agentui/markdown.test.ts
T
2026-09-29 01:58:28 +08:00

75 lines
2.5 KiB
TypeScript

import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it } from "vitest";
import { Markdown, parseMarkdown, safeHref } from "./markdown.tsx";
const html = (text: string) => renderToStaticMarkup(createElement(Markdown, { text }));
describe("Markdown 安全子集", () => {
it("块级:标题、列表、表格、代码块、引用、分隔线", () => {
const src = [
"## 结论",
"",
"**当前订阅 2 个**,来源 `inventory.query`:",
"",
"| # | 标题 | 年份 |",
"|---|:---|---:|",
"| 1 | 沙丘2 | 2024 |",
"| 2 | 沙丘:预言 | 2024 |",
"",
"- 缺 1080p",
"- 缺 4K",
"",
"1. 先搜",
"2. 再提交",
"",
"> 仅供参考",
"",
"---",
"```json",
'{"a":1}',
"```",
].join("\n");
const blocks = parseMarkdown(src);
expect(blocks.map((b) => b.type)).toEqual(["heading", "paragraph", "table", "list", "list", "quote", "hr", "code"]);
const out = html(src);
expect(out).toContain("<h4");
expect(out).toContain("<strong");
expect(out).toContain("<table");
expect(out).toContain("<td");
expect(out).toContain("沙丘:预言");
expect(out).toContain('<ol start="1"');
expect(out).toContain("<ul");
expect(out).toContain("<blockquote");
expect(out).toContain("<pre");
expect(out).toContain("text-align:right");
});
it("原文里的 HTML 按文字显示;危险链接不生成 <a>", () => {
const out = html(
"<script>alert(1)</script> <img src=x onerror=alert(1)> [点我](javascript:alert(1)) [文档](https://example.com/a)",
);
expect(out).not.toContain("<script");
expect(out).not.toContain("<img");
expect(out).toContain("&lt;script&gt;");
expect(out).not.toContain('href="javascript');
expect(out).toContain('href="https://example.com/a"');
expect(out).toContain('rel="noopener noreferrer nofollow"');
expect(safeHref("/console/tasks")).toBe("/console/tasks");
expect(safeHref("//evil.example")).toBeNull();
expect(safeHref("data:text/html,x")).toBeNull();
});
it("行内:代码里的星号不当强调;单换行保留为换行", () => {
const out = html("用 `a*b*c` 查询\n第二行 *强调*");
expect(out).toContain("<code");
expect(out).toContain("a*b*c");
expect(out).toContain("<br/>");
expect(out).toContain("<em>强调</em>");
});
it("空文本不渲染", () => {
expect(html(" \n\n")).toBe("");
});
});