diff --git a/.changeset/mts-cts-typescript-highlighting.md b/.changeset/mts-cts-typescript-highlighting.md new file mode 100644 index 00000000..3c759bcb --- /dev/null +++ b/.changeset/mts-cts-typescript-highlighting.md @@ -0,0 +1,5 @@ +--- +"hunkdiff": patch +--- + +Highlight `.mts` and `.cts` files as TypeScript instead of plain text. diff --git a/src/core/diffFile.test.ts b/src/core/diffFile.test.ts index 25740c36..2ed62988 100644 --- a/src/core/diffFile.test.ts +++ b/src/core/diffFile.test.ts @@ -36,6 +36,14 @@ describe("buildDiffFile", () => { expect(file.stats).toEqual({ additions: 2, deletions: 1 }); }); + test("derives TypeScript language for module and commonjs TypeScript files", () => { + const mtsFile = buildDiffFile(metadataFor("a\n", "b\n", "foo.mts"), "PATCH", 0, "src", null); + const ctsFile = buildDiffFile(metadataFor("a\n", "b\n", "foo.cts"), "PATCH", 1, "src", null); + + expect(mtsFile.language).toBe("typescript"); + expect(ctsFile.language).toBe("typescript"); + }); + test("infers binary status from the patch when not given explicitly", () => { const binary = buildDiffFile(metadata, "Binary files a/x and b/x differ\n", 0, "src", null); expect(binary.isBinary).toBe(true); diff --git a/src/core/diffFile.ts b/src/core/diffFile.ts index a80103fb..8ff0ff71 100644 --- a/src/core/diffFile.ts +++ b/src/core/diffFile.ts @@ -1,6 +1,7 @@ -import { getFiletypeFromFileName, type FileDiffMetadata } from "@pierre/diffs"; +import { type FileDiffMetadata } from "@pierre/diffs"; import { findAgentFileContext } from "./agent"; import { patchLooksBinary } from "./binary"; +import { getFiletypeFromFileName } from "./fileLanguage"; import { normalizeDiffMetadataPaths, normalizeDiffPath } from "./diffPaths"; import type { FileSourceFetcher } from "./fileSource"; import type { AgentContext, DiffFile, DiffLineMoveKinds } from "./types"; diff --git a/src/core/fileLanguage.test.ts b/src/core/fileLanguage.test.ts new file mode 100644 index 00000000..490fe41a --- /dev/null +++ b/src/core/fileLanguage.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, test } from "bun:test"; +import { getFiletypeFromFileName } from "./fileLanguage"; + +describe("custom file language registration", () => { + test("maps TypeScript module/commonjs extensions to typescript", () => { + expect(getFiletypeFromFileName("foo.mts")).toBe("typescript"); + expect(getFiletypeFromFileName("foo.cts")).toBe("typescript"); + expect(getFiletypeFromFileName("src/nested/foo.mts")).toBe("typescript"); + }); + + test("preserves Pierre's built-in extension detection", () => { + expect(getFiletypeFromFileName("foo.ts")).toBe("typescript"); + expect(getFiletypeFromFileName("foo.tsx")).toBe("tsx"); + expect(getFiletypeFromFileName("foo.mjs")).toBe("javascript"); + expect(getFiletypeFromFileName("foo.cjs")).toBe("javascript"); + }); +}); diff --git a/src/core/fileLanguage.ts b/src/core/fileLanguage.ts new file mode 100644 index 00000000..25f1dd3a --- /dev/null +++ b/src/core/fileLanguage.ts @@ -0,0 +1,17 @@ +import { + getFiletypeFromFileName, + setCustomExtension, + type SupportedLanguages, +} from "@pierre/diffs"; + +// Pierre omits these TypeScript extensions, so register them before lookups or rendering. +const HUNK_CUSTOM_EXTENSIONS: Record = { + mts: "typescript", + cts: "typescript", +}; + +for (const [extension, language] of Object.entries(HUNK_CUSTOM_EXTENSIONS)) { + setCustomExtension(extension, language); +} + +export { getFiletypeFromFileName };