Files
openclaw/ui/src/ui/markdown.test.ts
Ash (Bug Lab) 5084621f43 fix(ui): ensure GFM tables render in WebChat markdown (#20410)
- Pass gfm:true + breaks:true explicitly to marked.parse() so table
  support is guaranteed even if global setOptions() is bypassed or
  reset by a future refactor (defense-in-depth)
- Add display:block + overflow-x:auto to .chat-text table so wide
  multi-column tables scroll horizontally instead of being clipped
  by the parent overflow-x:hidden chat container
- Add regression tests for GFM table rendering in markdown.test.ts
2026-03-03 01:14:30 +00:00

86 lines
2.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { toSanitizedMarkdownHtml } from "./markdown.ts";
describe("toSanitizedMarkdownHtml", () => {
it("renders basic markdown", () => {
const html = toSanitizedMarkdownHtml("Hello **world**");
expect(html).toContain("<strong>world</strong>");
});
it("strips scripts and unsafe links", () => {
const html = toSanitizedMarkdownHtml(
[
"<script>alert(1)</script>",
"",
"[x](javascript:alert(1))",
"",
"[ok](https://example.com)",
].join("\n"),
);
expect(html).not.toContain("<script");
expect(html).not.toContain("javascript:");
expect(html).toContain("https://example.com");
});
it("renders fenced code blocks", () => {
const html = toSanitizedMarkdownHtml(["```ts", "console.log(1)", "```"].join("\n"));
expect(html).toContain("<pre>");
expect(html).toContain("<code");
expect(html).toContain("console.log(1)");
});
it("preserves img tags with src and alt from markdown images (#15437)", () => {
const html = toSanitizedMarkdownHtml("![Alt text](https://example.com/image.png)");
expect(html).toContain("<img");
expect(html).toContain('src="https://example.com/image.png"');
expect(html).toContain('alt="Alt text"');
});
it("preserves base64 data URI images (#15437)", () => {
const html = toSanitizedMarkdownHtml("![Chart](data:image/png;base64,iVBORw0KGgo=)");
expect(html).toContain("<img");
expect(html).toContain("data:image/png;base64,");
});
it("strips javascript image urls", () => {
const html = toSanitizedMarkdownHtml("![X](javascript:alert(1))");
expect(html).toContain("<img");
expect(html).not.toContain("javascript:");
expect(html).not.toContain("src=");
});
it("renders GFM markdown tables (#20410)", () => {
const md = [
"| Feature | Status |",
"|---------|--------|",
"| Tables | ✅ |",
"| Borders | ✅ |",
].join("\n");
const html = toSanitizedMarkdownHtml(md);
expect(html).toContain("<table");
expect(html).toContain("<thead");
expect(html).toContain("<th>");
expect(html).toContain("Feature");
expect(html).toContain("Tables");
expect(html).not.toContain("|---------|");
});
it("renders GFM tables surrounded by text (#20410)", () => {
const md = [
"Text before.",
"",
"| Col1 | Col2 |",
"|------|------|",
"| A | B |",
"",
"Text after.",
].join("\n");
const html = toSanitizedMarkdownHtml(md);
expect(html).toContain("<table");
expect(html).toContain("Col1");
expect(html).toContain("Col2");
// Pipes from table delimiters must not appear as raw text
expect(html).not.toContain("|------|");
});
});