1import { describe, expect, it } from "vite-plus/test";
2import { markdownHtmlContent, markdownWithHtml, parseMarkdownDocument } from "./markdownDocument";
3import { markdownImageSources } from "./markdownImageSources";
4
5describe("HTML in native Markdown", () => {
6 it("leaves code inside an HTML details block literal", () => {
7 const content =
8 '<details>\n<summary>Example</summary>\n\n```html\n<img src="literal.png">\n```\n\nUse `<img>` here.\n</details>';
9 const result = markdownHtmlContent(content);
10 expect(result).toContain('```html\n<img src="literal.png">\n```');
11 expect(result).toContain("Use `<img>` here.");
12 expect(result).not.toContain("<details>");
13 });
14 it("preserves screenshot URLs and captions from GitHub HTML image embeds", () => {
15 expect(
16 markdownHtmlContent(
17 '<img width="900" alt="Before > after [settings]" src="https://example.com/before.png?a=1&amp;b=2" />',
18 ),
19 ).toBe("![Before > after \\[settings\\]](<https://example.com/before.png?a=1\\&b=2>)");
20 expect(
21 markdownHtmlContent(
22 "<a href='https://example.com'><img src='https://example.com/banner.svg' alt='Review' /></a>",
23 ),
24 ).toBe("![Review](<https://example.com/banner.svg>)");
25 });
26
27 it("decodes HTML attributes once and preserves entity-shaped query values through Markdown", () => {
28 const markdown =
29 '<img alt="&amp;lt;" src="https://example.com/shot.png?label=&amp;lt;&amp;sig=a%26b">';
30 expect(markdownWithHtml(markdown)).toBe(
31 "![\\&lt;](<https://example.com/shot.png?label=\\&lt;\\&sig=a%26b>)",
32 );
33 expect(markdownImageSources(markdown)).toEqual([
34 "https://example.com/shot.png?label=&lt;&sig=a%26b",
35 ]);
36 const paragraph = parseMarkdownDocument(markdown).children[0];
37 expect(paragraph?.type).toBe("paragraph");
38 if (paragraph?.type === "paragraph")
39 expect(paragraph.children[0]).toMatchObject({ type: "image", alt: "&lt;" });
40 });
41
42 it("ignores code delimiters in HTML attributes and comments when collecting screenshots", () => {
43 const markdown =
44 '<details data-example="`">\n<summary>Proof</summary>\n<img src="https://example.com/shot.png" alt="Screenshot">\n<!-- ` -->\n</details>';
45 expect(markdownHtmlContent(markdown)).toContain(
46 "![Screenshot](<https://example.com/shot.png>)",
47 );
48 expect(markdownImageSources(markdown)).toEqual(["https://example.com/shot.png"]);
49 expect(markdownWithHtml(markdown)).not.toContain("<img");
50 });
51
52 it("removes bot metadata and details wrappers while keeping the content", () => {
53 const markdown =
54 "<!-- generated bot metadata -->\n<details>\n<summary>Walkthrough</summary>\n\n## Changes\n\nText\n\n</details>";
55 const result = markdownWithHtml(markdown);
56 expect(result).not.toContain("<!--");
57 expect(result).not.toContain("<details>");
58 expect(result).toContain("**Walkthrough**");
59 expect(result).toContain("## Changes");
60 expect(parseMarkdownDocument(markdown).children.some((node) => node.type === "html")).toBe(
61 false,
62 );
63 });
64
65 it("collects HTML and Markdown screenshots while leaving inline and fenced code literal", () => {
66 const markdown =
67 '```html\n<img src="literal.png">\n```\n\nUse `<img src="inline.png">` here.\n\n<img src="one.png">\n\n![Two](two.png)\n\n<img src="one.png">';
68 expect(markdownImageSources(markdown)).toEqual(["one.png", "two.png"]);
69 const result = markdownWithHtml(markdown);
70 expect(result).toContain('```html\n<img src="literal.png">\n```');
71 expect(result).toContain('`<img src="inline.png">`');
72 });
73});