feat: expand diff syntax highlighting languages

This commit is contained in:
Mohamed Boudra
2026-03-19 15:44:04 +07:00
parent 9065dcef54
commit 7609ccee4c
7 changed files with 599 additions and 0 deletions
@@ -59,6 +59,105 @@ index 1234567..0000000
-export { legacy };
`;
const RUST_DIFF = `diff --git a/lib.rs b/lib.rs
index 1234567..abcdefg 100644
--- a/lib.rs
+++ b/lib.rs
@@ -1,4 +1,4 @@
fn main() {
- let version = 1;
+ let version = 2;
println!("Hello, world!");
}
`;
const C_DIFF = `diff --git a/example.c b/example.c
index 1234567..abcdefg 100644
--- a/example.c
+++ b/example.c
@@ -1,4 +1,4 @@
int main(void) {
- int version = 1;
+ int version = 2;
return version;
}
`;
const JAVA_DIFF = `diff --git a/Main.java b/Main.java
index 1234567..abcdefg 100644
--- a/Main.java
+++ b/Main.java
@@ -1,5 +1,5 @@
public class Main {
public static void main(String[] args) {
- int version = 1;
+ int version = 2;
}
}
`;
const OBJECTIVE_C_DIFF = `diff --git a/AppDelegate.m b/AppDelegate.m
index 1234567..abcdefg 100644
--- a/AppDelegate.m
+++ b/AppDelegate.m
@@ -1,4 +1,4 @@
int main(void) {
- int version = 1;
+ int version = 2;
return version;
}
`;
const GO_DIFF = `diff --git a/main.go b/main.go
index 1234567..abcdefg 100644
--- a/main.go
+++ b/main.go
@@ -1,7 +1,7 @@
package main
import "fmt"
func main() {
- version := 1
+ version := 2
fmt.Println(version)
}
`;
const PHP_DIFF = `diff --git a/index.php b/index.php
index 1234567..abcdefg 100644
--- a/index.php
+++ b/index.php
@@ -1,4 +1,4 @@
<?php
-$version = 1;
+$version = 2;
echo $version;
?>
`;
const YAML_DIFF = `diff --git a/config.yaml b/config.yaml
index 1234567..abcdefg 100644
--- a/config.yaml
+++ b/config.yaml
@@ -1,3 +1,3 @@
app: paseo
-count: 1
+count: 2
enabled: true
`;
const XML_DIFF = `diff --git a/config.xml b/config.xml
index 1234567..abcdefg 100644
--- a/config.xml
+++ b/config.xml
@@ -1,3 +1,3 @@
<config>
- <count>1</count>
+ <count>2</count>
</config>
`;
describe("parseDiff", () => {
it("parses a simple diff with one hunk", () => {
const files = parseDiff(SIMPLE_DIFF);
@@ -251,6 +350,124 @@ describe("highlightDiffFile", () => {
expect(highlighted.hunks[0].lines[1].tokens).toBeUndefined();
expect(highlighted.hunks[0].lines[2].tokens).toBeUndefined();
});
it("adds syntax highlighting tokens to Rust code", () => {
const files = parseDiff(RUST_DIFF);
const highlighted = highlightDiffFile(files[0]);
const hunk = highlighted.hunks[0];
const fnLine = hunk.lines[1];
expect(fnLine.tokens).toBeDefined();
expect(fnLine.tokens!.some((t) => t.text === "fn" && t.style === "keyword")).toBe(true);
const addedLine = hunk.lines.find(
(line) => line.type === "add" && line.content.includes("version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to C code", () => {
const files = parseDiff(C_DIFF);
const highlighted = highlightDiffFile(files[0]);
const hunk = highlighted.hunks[0];
const mainLine = hunk.lines[1];
expect(mainLine.tokens).toBeDefined();
expect(mainLine.tokens!.length).toBeGreaterThan(0);
const addedLine = hunk.lines.find(
(line) => line.type === "add" && line.content.includes("version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to Java code", () => {
const files = parseDiff(JAVA_DIFF);
const highlighted = highlightDiffFile(files[0]);
const hunk = highlighted.hunks[0];
const classLine = hunk.lines[1];
expect(classLine.tokens).toBeDefined();
expect(
classLine.tokens!.some((t) => t.text === "public" && t.style === "keyword")
).toBe(true);
const addedLine = hunk.lines.find(
(line) => line.type === "add" && line.content.includes("version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to Objective-C file extensions", () => {
const files = parseDiff(OBJECTIVE_C_DIFF);
const highlighted = highlightDiffFile(files[0]);
const hunk = highlighted.hunks[0];
const addedLine = hunk.lines.find(
(line) => line.type === "add" && line.content.includes("version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to Go code", () => {
const files = parseDiff(GO_DIFF);
const highlighted = highlightDiffFile(files[0]);
const addedLine = highlighted.hunks[0].lines.find(
(line) => line.type === "add" && line.content.includes("version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to PHP code", () => {
const files = parseDiff(PHP_DIFF);
const highlighted = highlightDiffFile(files[0]);
const addedLine = highlighted.hunks[0].lines.find(
(line) => line.type === "add" && line.content.includes("$version")
);
expect(addedLine?.tokens).toBeDefined();
expect(
addedLine!.tokens!.some((t) => t.text === "2" && t.style === "number")
).toBe(true);
});
it("adds syntax highlighting tokens to YAML code", () => {
const files = parseDiff(YAML_DIFF);
const highlighted = highlightDiffFile(files[0]);
const addedLine = highlighted.hunks[0].lines.find(
(line) => line.type === "add" && line.content.includes("count")
);
expect(addedLine?.tokens).toBeDefined();
expect(addedLine!.tokens!.length).toBeGreaterThan(0);
});
it("adds syntax highlighting tokens to XML code", () => {
const files = parseDiff(XML_DIFF);
const highlighted = highlightDiffFile(files[0]);
const addedLine = highlighted.hunks[0].lines.find(
(line) => line.type === "add" && line.content.includes("<count>")
);
expect(addedLine?.tokens).toBeDefined();
expect(addedLine!.tokens!.some((t) => t.style === "tag")).toBe(true);
});
});
describe("parseAndHighlightDiff", () => {
@@ -2,9 +2,16 @@ import { highlightTree, tagHighlighter, tags } from "@lezer/highlight";
import { parser as jsParser } from "@lezer/javascript";
import { parser as jsonParser } from "@lezer/json";
import { parser as cssParser } from "@lezer/css";
import { parser as cppParser } from "@lezer/cpp";
import { parser as goParser } from "@lezer/go";
import { parser as htmlParser } from "@lezer/html";
import { parser as javaParser } from "@lezer/java";
import { parser as pythonParser } from "@lezer/python";
import { parser as markdownParser } from "@lezer/markdown";
import { parser as phpParser } from "@lezer/php";
import { parser as rustParser } from "@lezer/rust";
import { parser as xmlParser } from "@lezer/xml";
import { parser as yamlParser } from "@lezer/yaml";
import { parser as elixirParser } from "lezer-elixir";
import type { Parser } from "@lezer/common";
@@ -17,6 +24,16 @@ const parsersByExtension: Record<string, Parser> = {
tsx: jsParser.configure({ dialect: "tsx jsx" }),
mjs: jsParser,
cjs: jsParser,
// C / C++ / Objective-C
c: cppParser,
h: cppParser,
cc: cppParser,
cpp: cppParser,
cxx: cppParser,
hpp: cppParser,
hxx: cppParser,
m: cppParser,
mm: cppParser,
// JSON
json: jsonParser,
// CSS
@@ -25,8 +42,21 @@ const parsersByExtension: Record<string, Parser> = {
// HTML
html: htmlParser,
htm: htmlParser,
// XML
xml: xmlParser,
// Java
java: javaParser,
// Python
py: pythonParser,
// Go
go: goParser,
// PHP
php: phpParser,
// YAML
yaml: yamlParser,
yml: yamlParser,
// Rust
rs: rustParser,
// Elixir
ex: elixirParser,
exs: elixirParser,