882 lines · 23.3 KB · TypeScript
RawDownload
import { describe, expect, it } from "vite-plus/test";import type { MarkdownNode } from "react-native-nitro-markdown/headless"; import {  nativeMarkdownChunkSpacing,  nativeMarkdownDocumentChunks,  nativeMarkdownDocumentRuns,  nativeMarkdownListItemBlocks,  nativeMarkdownTextRuns,  nativeMarkdownWithPreservedSoftBreaks,} from "@t3tools/mobile-markdown-text/markdown"; describe("nativeMarkdownTextRuns", () => {  it("links a path-shaped code span without changing the same path in prose", () => {    expect(      nativeMarkdownTextRuns({        type: "paragraph",        children: [          { type: "text", content: "/tmp/frame.png " },          { type: "code_inline", content: "/tmp/frame.png" },        ],      }),    ).toEqual([      { text: "/tmp/frame.png " },      { text: "frame.png", href: "/tmp/frame.png", fileIcon: "image" },    ]);  });   it("preserves the destination of a link with a code-formatted label", () => {    expect(      nativeMarkdownTextRuns({        type: "paragraph",        children: [          {            type: "link",            href: "https://example.com/docs",            children: [{ type: "code_inline", content: "src/main.ts" }],          },        ],      }),    ).toEqual([      {        text: "src/main.ts",        code: true,        href: "https://example.com/docs",        externalHost: "example.com",      },    ]);  });   it("preserves inline emphasis and code styles", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        { type: "text", content: "plain " },        { type: "bold", children: [{ type: "text", content: "bold" }] },        { type: "text", content: " " },        { type: "code_inline", content: "const value = 1" },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([      { text: "plain " },      { text: "bold", bold: true },      { text: " " },      { text: "const value = 1", code: true },    ]);  });   it("normalizes external and file links for native presentation", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        {          type: "link",          href: "https://example.com/docs",          children: [{ type: "text", content: "Docs" }],        },        { type: "text", content: " " },        {          type: "link",          href: "file:///repo/README.md#L12",          children: [{ type: "text", content: "ignored label" }],        },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([      {        text: "Docs",        href: "https://example.com/docs",        externalHost: "example.com",      },      { text: " " },      {        text: "README.md:12",        href: "file:///repo/README.md#L12",        fileIcon: "readme",      },    ]);  });   it("keeps hard breaks and collapses soft breaks", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        { type: "text", content: "first" },        { type: "soft_break" },        { type: "text", content: "second" },        { type: "line_break" },        { type: "text", content: "third" },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([{ text: "first second\nthird" }]);  });   it("can preserve soft breaks for authored user messages", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        { type: "text", content: "first" },        { type: "soft_break" },        { type: "text", content: "second" },      ],    };     expect(nativeMarkdownTextRuns(nativeMarkdownWithPreservedSoftBreaks(node))).toEqual([      { text: "first\nsecond" },    ]);  });   it("normalizes common inline HTML and entities", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        { type: "text", content: "Less than: &lt; " },        { type: "html_inline", content: "<kbd>" },        { type: "text", content: "⌘" },        { type: "html_inline", content: "</kbd>" },        { type: "html_inline", content: "<br />" },        { type: "html_inline", content: "<mark>highlighted</mark>" },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([{ text: "Less than: < ⌘\nhighlighted" }]);  });   it("normalizes double-encoded entities and inline tags emitted as text", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        {          type: "text",          content:            "Keyboard: <kbd>⌘</kbd> + <kbd>K</kbd>; Less than: &amp;lt;; Greater than: &amp;gt;",        },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([      { text: "Keyboard: ⌘ + K; Less than: <; Greater than: >" },    ]);  });   it.each([    ["&#128512;", "😀"],    ["&#x1f680;", "🚀"],    ["&#9999999999;", "&#9999999999;"],    ["&#x110000;", "&#x110000;"],    ["&amp;#9999999999;", "&#9999999999;"],    ["&amp;#x110000;", "&#x110000;"],  ])("normalizes numeric entity %s without throwing", (content, expected) => {    const node: MarkdownNode = {      type: "paragraph",      children: [{ type: "text", content }],    };     expect(nativeMarkdownTextRuns(node)).toEqual([{ text: expected }]);  });   it("reads inline content from nested text nodes", () => {    const node: MarkdownNode = {      type: "paragraph",      children: [        {          type: "text",          children: [{ type: "text", content: "Plain text" }],        },        { type: "text", content: " and " },        {          type: "code_inline",          children: [{ type: "text", content: "inline code" }],        },      ],    };     expect(nativeMarkdownTextRuns(node)).toEqual([      { text: "Plain text and " },      { text: "inline code", code: true },    ]);  });}); describe("nativeMarkdownDocumentRuns", () => {  it("decorates known skill references as selectable skill links", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "paragraph",          children: [{ type: "text", content: "Use $ui for this." }],        },      ],    };     expect(nativeMarkdownDocumentRuns(node, [{ name: "ui", displayName: "UI" }])).toEqual([      { text: "Use ", role: "body" },      {        text: "$ui",        role: "body",        skillName: "ui",        skillLabel: "UI",      },      { text: " for this.", role: "body" },    ]);  });   it("decorates known skill references that begin with a digit", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "paragraph",          children: [{ type: "text", content: "Use $2spec for this." }],        },      ],    };     expect(nativeMarkdownDocumentRuns(node, [{ name: "2spec", displayName: "2Spec" }])).toEqual([      { text: "Use ", role: "body" },      {        text: "$2spec",        role: "body",        skillName: "2spec",        skillLabel: "2Spec",      },      { text: " for this.", role: "body" },    ]);  });   it("decorates known skill references inside blockquotes", () => {    const node: MarkdownNode = {      type: "blockquote",      children: [        {          type: "paragraph",          children: [{ type: "text", content: "Use $ui for this." }],        },      ],    };     expect(nativeMarkdownDocumentRuns(node, [{ name: "ui", displayName: "UI" }])).toContainEqual({      text: "$ui",      role: "body",      skillName: "ui",      skillLabel: "UI",    });  });   it("leaves unknown skill-like text unchanged", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "paragraph",          children: [{ type: "text", content: "Use $unknown for this." }],        },      ],    };     expect(nativeMarkdownDocumentRuns(node, [])).toEqual([      { text: "Use $unknown for this.", role: "body" },    ]);  });   it("keeps headings, paragraphs, and lists in one continuous document", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "heading",          level: 1,          children: [{ type: "text", content: "Header One" }],        },        {          type: "paragraph",          children: [            { type: "text", content: "A paragraph with " },            { type: "bold", children: [{ type: "text", content: "bold text" }] },            { type: "text", content: "." },          ],        },        {          type: "list",          ordered: false,          children: [            {              type: "list_item",              children: [                {                  type: "paragraph",                  children: [{ type: "text", content: "First item" }],                },              ],            },            {              type: "list_item",              children: [                {                  type: "paragraph",                  children: [{ type: "text", content: "Second item" }],                },              ],            },          ],        },      ],    };     const runs = nativeMarkdownDocumentRuns(node);    expect(runs.map((run) => run.text).join("")).toBe(      "Header One\n\nA paragraph with bold text.\n\n•\tFirst item\n•\tSecond item",    );    expect(runs).toContainEqual({      text: "Header One\n",      role: "heading",      headingLevel: 1,    });    expect(runs).toContainEqual({      text: "bold text",      bold: true,      role: "body",    });    expect(runs).toContainEqual({      text: "•\t",      role: "list-marker",      depth: 1,      firstLineHeadIndent: 0,      headIndent: 24,      paragraphSpacing: 2,    });  });   it("uses distinct section, heading-content, and body spacing", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "paragraph",          children: [{ type: "text", content: "Intro" }],        },        {          type: "heading",          level: 2,          children: [{ type: "text", content: "Section" }],        },        {          type: "paragraph",          children: [{ type: "text", content: "First paragraph" }],        },        {          type: "paragraph",          children: [{ type: "text", content: "Second paragraph" }],        },      ],    };     expect(      nativeMarkdownDocumentRuns(node)        .filter((run) => run.role === "spacer")        .map((run) => run.spacing),    ).toEqual([20, 10, 12]);  });   it("renders tight list items whose inline nodes are direct children", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "list",          children: [            {              type: "list_item",              children: [                {                  type: "bold",                  children: [{ type: "text", content: "Finding:" }],                },                { type: "text", content: " details with " },                { type: "code_inline", content: "inline code" },                { type: "text", content: "." },              ],            },          ],        },      ],    };     expect(nativeMarkdownDocumentRuns(node)).toEqual([      {        text: "•\t",        role: "list-marker",        depth: 1,        firstLineHeadIndent: 0,        headIndent: 24,        paragraphSpacing: 2,      },      { text: "Finding:", bold: true, role: "body", depth: 1 },      { text: " details with ", role: "body", depth: 1 },      { text: "inline code", code: true, role: "body", depth: 1 },      { text: ".", role: "body", depth: 1 },    ]);  });   it("preserves quotes and fenced code in document runs", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "blockquote",          children: [            {              type: "paragraph",              children: [{ type: "text", content: "Read this" }],            },          ],        },        {          type: "code_block",          language: "ts",          content: "const answer = 42;",        },      ],    };     const runs = nativeMarkdownDocumentRuns(node);    expect(runs.map((run) => run.text).join("")).toBe("│\u00a0Read this\n\nTS\nconst answer = 42;");    expect(runs).toContainEqual({      text: "const answer = 42;",      code: true,      role: "code-block",    });  });   it("reads fenced code content from child text nodes", () => {    const node: MarkdownNode = {      type: "document",      children: [        {          type: "code_block",          language: "bash",          children: [{ type: "text", content: "pnpm install\n" }],        },      ],    };     expect(      nativeMarkdownDocumentRuns(node)        .map((run) => run.text)        .join(""),    ).toBe("BASH\npnpm install");  });}); describe("nativeMarkdownListItemBlocks", () => {  it("groups consecutive inline nodes into one paragraph block", () => {    const item: MarkdownNode = {      type: "list_item",      children: [        { type: "text", content: "Finding: " },        { type: "bold", children: [{ type: "text", content: "important" }] },        { type: "text", content: " details." },        {          type: "list",          children: [            {              type: "list_item",              children: [{ type: "text", content: "Nested" }],            },          ],        },        { type: "text", content: "Trailing prose." },      ],    };     expect(nativeMarkdownListItemBlocks(item)).toEqual([      {        type: "paragraph",        children: item.children?.slice(0, 3),

Lines 1–500 of 882.