// Diffs tests cover language hints plugin behavior. import type { FileDiffMetadata } from "@pierre/diffs"; import { describe, expect, it } from "vitest"; import { normalizeDiffViewerPayloadLanguages, normalizeSupportedLanguageHint, } from "./language-hints.js"; async function normalizeHints(values: readonly string[], options = {}) { return await Promise.all(values.map((value) => normalizeSupportedLanguageHint(value, options))); } describe("normalizeSupportedLanguageHint", () => { it("keeps supported languages", async () => { await expect(normalizeHints(["typescript", "cpp", "text"])).resolves.toEqual([ "typescript", "cpp", "text", ]); }); it("normalizes common aliases to base viewer languages", async () => { await expect( normalizeHints(["ts", "c++", "c#", "bash", "dockerfile", "rb", "kt", "ps1"]), ).resolves.toEqual([ "typescript", "cpp", "csharp", "sh", "docker", "ruby", "kotlin", "powershell", ]); }); it("keeps mainstream languages in the base viewer without the language pack", async () => { await expect( normalizeHints([ "ruby", "swift", "kotlin", "r", "dart", "lua", "powershell", "xml", "toml", ]), ).resolves.toEqual([ "ruby", "swift", "kotlin", "r", "dart", "lua", "powershell", "xml", "toml", ]); }); it("drops uncommon languages without the language pack", async () => { await expect(normalizeSupportedLanguageHint("abap")).resolves.toBeUndefined(); }); it("keeps uncommon languages when the language pack is available", async () => { await expect( normalizeSupportedLanguageHint("abap", { languagePackAvailable: true }), ).resolves.toBe("abap"); }); it("drops invalid languages", async () => { await expect(normalizeSupportedLanguageHint("not-a-real-language")).resolves.toBeUndefined(); }); it("keeps valid languages when invalid hints are mixed in", async () => { await expect(normalizeHints(["typescript", "not-a-real-language"])).resolves.toEqual([ "typescript", undefined, ]); }); }); describe("normalizeDiffViewerPayloadLanguages", () => { it("rewrites stale patch payload language overrides to plain text", async () => { const result = await normalizeDiffViewerPayloadLanguages({ prerenderedHTML: "
diff
", options: { theme: { light: "pierre-light", dark: "pierre-dark", }, diffStyle: "unified", diffIndicators: "bars", disableLineNumbers: false, expandUnchanged: false, themeType: "dark", backgroundEnabled: true, overflow: "wrap", unsafeCSS: "", }, langs: ["not-a-real-language" as never], fileDiff: { name: "foo.txt", lang: "not-a-real-language" as never, } as unknown as FileDiffMetadata, }); expect(result.langs).toEqual(["text"]); expect(result.fileDiff?.lang).toBe("text"); }); it("keeps valid hydrated languages and only downgrades invalid sides", async () => { const result = await normalizeDiffViewerPayloadLanguages({ prerenderedHTML: "
diff
", options: { theme: { light: "pierre-light", dark: "pierre-dark", }, diffStyle: "split", diffIndicators: "classic", disableLineNumbers: true, expandUnchanged: true, themeType: "light", backgroundEnabled: false, overflow: "scroll", unsafeCSS: "", }, langs: ["typescript", "not-a-real-language" as never], oldFile: { name: "before.unknown", contents: "before", lang: "not-a-real-language" as never, }, newFile: { name: "after.ts", contents: "after", lang: "typescript", }, }); expect(result.langs).toEqual(["typescript", "text"]); expect(result.oldFile?.lang).toBe("text"); expect(result.newFile?.lang).toBe("typescript"); }); it("keeps uncommon hydrated languages when the language pack is available", async () => { const result = await normalizeDiffViewerPayloadLanguages( { prerenderedHTML: "
diff
", options: { theme: { light: "pierre-light", dark: "pierre-dark", }, diffStyle: "unified", diffIndicators: "bars", disableLineNumbers: false, expandUnchanged: false, themeType: "dark", backgroundEnabled: true, overflow: "wrap", unsafeCSS: "", }, langs: ["abap" as never], fileDiff: { name: "demo.abap", lang: "abap" as never, } as unknown as FileDiffMetadata, }, { languagePackAvailable: true }, ); expect(result.langs).toEqual(["abap"]); expect(result.fileDiff?.lang).toBe("abap"); }); it("rewrites blank explicit language overrides to plain text", async () => { const result = await normalizeDiffViewerPayloadLanguages({ prerenderedHTML: "
diff
", options: { theme: { light: "pierre-light", dark: "pierre-dark", }, diffStyle: "unified", diffIndicators: "bars", disableLineNumbers: false, expandUnchanged: false, themeType: "dark", backgroundEnabled: true, overflow: "wrap", unsafeCSS: "", }, langs: [" " as never], oldFile: { name: "before.unknown", contents: "before", lang: " " as never, }, newFile: { name: "after.txt", contents: "after", }, }); expect(result.langs).toEqual(["text"]); expect(result.oldFile?.lang).toBe("text"); }); it("does not inject text when a valid file language is the only supported hint", async () => { const result = await normalizeDiffViewerPayloadLanguages({ prerenderedHTML: "
diff
", options: { theme: { light: "pierre-light", dark: "pierre-dark", }, diffStyle: "unified", diffIndicators: "bars", disableLineNumbers: false, expandUnchanged: false, themeType: "dark", backgroundEnabled: true, overflow: "wrap", unsafeCSS: "", }, langs: [], oldFile: { name: "before.ts", contents: "before", lang: "typescript", }, newFile: { name: "after.ts", contents: "after", lang: "typescript", }, }); expect(result.langs).toEqual(["typescript"]); }); });