| 1 | import { expect, it, vi } from "vite-plus/test"; |
| 2 | |
| 3 | const { getSharedHighlighter } = vi.hoisted(() => ({ |
| 4 | getSharedHighlighter: vi.fn(), |
| 5 | })); |
| 6 | |
| 7 | vi.mock("@pierre/diffs", () => ({ |
| 8 | getSharedHighlighter, |
| 9 | })); |
| 10 | |
| 11 | import { getSyntaxHighlighterPromise } from "./syntaxHighlighting"; |
| 12 | |
| 13 | it("caches the recovered text highlighter for unsupported languages", async () => { |
| 14 | const actual = await vi.importActual<typeof import("@pierre/diffs")>("@pierre/diffs"); |
| 15 | const textHighlighter = await actual.getSharedHighlighter({ |
| 16 | themes: ["pierre-dark", "pierre-light"], |
| 17 | langs: ["text"], |
| 18 | preferredHighlighter: "shiki-wasm", |
| 19 | }); |
| 20 | getSharedHighlighter.mockImplementation(({ langs }: { langs: string[] }) => |
| 21 | langs[0] === "text" |
| 22 | ? Promise.resolve(textHighlighter) |
| 23 | : Promise.reject(new Error("unsupported language")), |
| 24 | ); |
| 25 | |
| 26 | const first = getSyntaxHighlighterPromise("unsupported-test-language"); |
| 27 | await expect(first).resolves.toBe(textHighlighter); |
| 28 | const second = getSyntaxHighlighterPromise("unsupported-test-language"); |
| 29 | |
| 30 | expect(second).toBe(first); |
| 31 | expect(getSharedHighlighter).toHaveBeenCalledTimes(2); |
| 32 | }); |
| 33 | |
| 34 | it("keeps neutral syntax colors readable on the active code surface", async () => { |
| 35 | const actual = await vi.importActual<typeof import("@pierre/diffs")>("@pierre/diffs"); |
| 36 | getSharedHighlighter.mockImplementation(actual.getSharedHighlighter); |
| 37 | const highlighter = await getSyntaxHighlighterPromise("typescript"); |
| 38 | |
| 39 | for (const theme of ["pierre-light", "pierre-dark"] as const) { |
| 40 | const { tokens } = highlighter.codeToTokens("// comment\nconst value: string = 'text';", { |
| 41 | lang: "typescript", |
| 42 | theme, |
| 43 | }); |
| 44 | const comment = tokens.flat().find((token) => token.content === "// comment"); |
| 45 | const punctuation = tokens.flat().find((token) => token.content === ":"); |
| 46 | const keyword = tokens.flat().find((token) => token.content === "const"); |
| 47 | |
| 48 | expect(comment?.color).toBe( |
| 49 | "color-mix(in srgb, var(--code-foreground) 80%, var(--code-background))", |
| 50 | ); |
| 51 | expect(punctuation?.color).toBe("var(--code-foreground)"); |
| 52 | expect(keyword?.color).toMatch(/^#[\dA-F]{6}$/); |
| 53 | expect( |
| 54 | highlighter.codeToHtml("// comment\nconst value: string = 'text';", { |
| 55 | lang: "typescript", |
| 56 | theme, |
| 57 | }), |
| 58 | ).toContain("color:var(--code-foreground)"); |
| 59 | } |
| 60 | }); |