markdown.test.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { afterEach, describe, expect, it } from "vitest";
  2. import { renderMarkdown } from "../markdown.js";
  3. describe("renderMarkdown", () => {
  4. const origTermProgram = process.env.TERM_PROGRAM;
  5. afterEach(() => {
  6. if (origTermProgram === undefined) delete process.env.TERM_PROGRAM;
  7. else process.env.TERM_PROGRAM = origTermProgram;
  8. });
  9. it("converts **text** to ANSI bold", () => {
  10. const result = renderMarkdown("这是 **加粗** 文本");
  11. // Should contain ANSI bold on/off around 加粗
  12. expect(result).toContain("\x1b[1m加粗\x1b[22m");
  13. // Should NOT contain raw ** markers
  14. expect(result).not.toContain("**");
  15. });
  16. it("converts * bullets to · bullets", () => {
  17. const result = renderMarkdown("* 第一项\n* 第二项");
  18. expect(result).toContain("· 第一项");
  19. expect(result).toContain("· 第二项");
  20. // No raw * bullets remaining
  21. expect(result).not.toMatch(/^\s*\* /m);
  22. });
  23. it("renders bold inside list items", () => {
  24. const result = renderMarkdown("* **昨日**: 总统套房\n* **今日**: 桥洞");
  25. expect(result).toContain("\x1b[1m昨日\x1b[22m");
  26. expect(result).toContain("\x1b[1m今日\x1b[22m");
  27. expect(result).toContain("·");
  28. expect(result).not.toContain("**");
  29. });
  30. it("does not leak bold across lines", () => {
  31. const result = renderMarkdown("打磨**冲突场景**,还是梳理**心理转变弧线**。");
  32. // Each bold region should be self-contained
  33. const boldRegions = [...result.matchAll(/\x1b\[1m(.*?)\x1b\[22m/g)];
  34. expect(boldRegions).toHaveLength(2);
  35. expect(boldRegions[0][1]).toBe("冲突场景");
  36. expect(boldRegions[1][1]).toBe("心理转变弧线");
  37. });
  38. it("renders tables with box-drawing characters", () => {
  39. const result = renderMarkdown(
  40. "| 属性 | 值 |\n|------|----|\n| 住所 | 桥洞 |",
  41. );
  42. expect(result).toContain("┌");
  43. expect(result).toContain("│");
  44. expect(result).toContain("└");
  45. });
  46. it("does not contain full-reset codes that override parent Ink color", () => {
  47. // \x1b[0m resets ALL terminal attributes including color set by Ink's <Text>.
  48. // renderMarkdown must not emit it, so the parent <Text color={...}> stays in effect.
  49. const result = renderMarkdown("这是 **加粗** 文本");
  50. expect(result).not.toContain("\x1b[0m");
  51. });
  52. it("falls back to raw text on parse error", () => {
  53. // renderMarkdown should never throw; it returns raw text on failure
  54. const result = renderMarkdown("plain text");
  55. expect(result).toContain("plain text");
  56. });
  57. });