Files
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

64 lines
2.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { renderMarkdown } from "../../src/lib/markdown";
describe("renderMarkdown", () => {
it("renders standard markdown", () => {
const html = renderMarkdown("# Title\n\n**bold** and *italic*");
expect(html).toContain("<h1>Title</h1>");
expect(html).toContain("<strong>bold</strong>");
expect(html).toContain("<em>italic</em>");
});
it("strips a <script> tag", () => {
const html = renderMarkdown("ok\n\n<script>alert(1)</script>");
expect(html).not.toContain("<script");
expect(html).not.toContain("alert(1)");
});
it("drops raw HTML blocks, including event-handler attributes", () => {
const html = renderMarkdown('<div onclick="steal()">hi</div>');
expect(html).not.toContain("<div");
expect(html).not.toContain("onclick");
});
it("drops images entirely so nothing loads from a foreign host", () => {
const html = renderMarkdown("![alt text](https://evil.example/tracker.png)");
expect(html).not.toContain("<img");
expect(html).not.toContain("evil.example");
expect(html).toContain("alt text");
});
it("renders an https link with target=_blank and rel=noopener noreferrer", () => {
const html = renderMarkdown("[ok](https://example.com)");
expect(html).toContain('href="https://example.com"');
expect(html).toContain('rel="noopener noreferrer"');
expect(html).toContain('target="_blank"');
});
it("renders inline markdown inside link text", () => {
const html = renderMarkdown("[**bold** link](https://example.com)");
expect(html).toContain('href="https://example.com"');
expect(html).toContain("<strong>bold</strong>");
expect(html).not.toContain("**bold**");
});
it("drops a javascript: link, keeping only its text", () => {
const html = renderMarkdown("[click](javascript:alert(1))");
expect(html).not.toContain("javascript:");
expect(html).not.toContain("<a");
expect(html).toContain("click");
});
it("drops a data: link", () => {
const html = renderMarkdown("[x](data:text/html,<script>alert(1)</script>)");
expect(html).not.toContain("data:");
expect(html).not.toContain("<script");
});
it("never emits an inline style attribute", () => {
const html = renderMarkdown('<p style="position:fixed;inset:0">x</p>');
expect(html).not.toContain("style=");
});
});