Skip to content

Commit a542435

Browse files
Copilotdwjohnston
andcommitted
Fix syntax highlighting for React/TypeScript files by adding language detection
Co-authored-by: dwjohnston <[email protected]>
1 parent f6a8409 commit a542435

File tree

4 files changed

+164
-3
lines changed

4 files changed

+164
-3
lines changed

src/library/GithubPermalink/GithubPermalinkBase.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { SyntaxHighlight } from "../SyntaxHighlight/SyntaxHighlight";
66
import { formatForLineExclusions } from "./formatLineExclusions";
77
import { CopySvg } from "../images/CopySvg";
88
import { CopyButton } from "../common/CopyButton/CopyButton";
9+
import { getLanguageFromPath } from "../utils/getLanguageFromPath";
910

1011
export type GithubPermalinkBaseProps = {
1112
className?: string;
@@ -26,6 +27,7 @@ export function GithubPermalinkBase(props: GithubPermalinkBaseProps) {
2627
if (data.status === "ok") {
2728

2829
const formatedLineExclusions = formatForLineExclusions(data, excludeLines);
30+
const language = getLanguageFromPath(data.path);
2931

3032
const clipboard = formatedLineExclusions.reduce((acc, cur) => {
3133
if (cur.isExclude) {
@@ -41,11 +43,11 @@ export function GithubPermalinkBase(props: GithubPermalinkBaseProps) {
4143

4244
{formatedLineExclusions.map((v) => {
4345
if (v.isExclude) {
44-
return <SyntaxHighlight className="hide-line-numbers" text={excludeText} startingLineNumber={v.from} key={v.from}/>
46+
return <SyntaxHighlight className="hide-line-numbers" text={excludeText} startingLineNumber={v.from} language={language} key={v.from}/>
4547

4648
}
4749

48-
return <SyntaxHighlight text={v.lines.join("\n")} startingLineNumber={v.from} key={v.from}/>
50+
return <SyntaxHighlight text={v.lines.join("\n")} startingLineNumber={v.from} language={language} key={v.from}/>
4951

5052
})}
5153

src/library/SyntaxHighlight/SyntaxHighlight.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export function SyntaxHighlight(props: {
131131
language?: AvailableLanguagesPrism
132132
}) {
133133

134-
const { startingLineNumber, text, className } = props;
134+
const { startingLineNumber, text, className, language = "javascript" } = props;
135135

136136
const isDarkMode = useMediaQuery({ query: "(prefers-color-scheme: dark)" })
137137

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { getLanguageFromPath } from './getLanguageFromPath';
3+
4+
describe('getLanguageFromPath', () => {
5+
it('should return typescript for .tsx files', () => {
6+
expect(getLanguageFromPath('ReactRenders3.tsx')).toBe('typescript');
7+
});
8+
9+
it('should return typescript for .ts files', () => {
10+
expect(getLanguageFromPath('component.ts')).toBe('typescript');
11+
});
12+
13+
it('should return javascript for .js files', () => {
14+
expect(getLanguageFromPath('script.js')).toBe('javascript');
15+
});
16+
17+
it('should return javascript for .jsx files', () => {
18+
expect(getLanguageFromPath('component.jsx')).toBe('javascript');
19+
});
20+
21+
it('should return python for .py files', () => {
22+
expect(getLanguageFromPath('script.py')).toBe('python');
23+
});
24+
25+
it('should return go for .go files', () => {
26+
expect(getLanguageFromPath('main.go')).toBe('go');
27+
});
28+
29+
it('should return html for .html files', () => {
30+
expect(getLanguageFromPath('index.html')).toBe('html');
31+
});
32+
33+
it('should return css for .css files', () => {
34+
expect(getLanguageFromPath('styles.css')).toBe('css');
35+
});
36+
37+
it('should return json for .json files', () => {
38+
expect(getLanguageFromPath('package.json')).toBe('json');
39+
});
40+
41+
it('should return markdown for .md files', () => {
42+
expect(getLanguageFromPath('README.md')).toBe('markdown');
43+
});
44+
45+
it('should return yaml for .yaml files', () => {
46+
expect(getLanguageFromPath('config.yaml')).toBe('yaml');
47+
});
48+
49+
it('should return yaml for .yml files', () => {
50+
expect(getLanguageFromPath('config.yml')).toBe('yaml');
51+
});
52+
53+
it('should return javascript as fallback for unknown extensions', () => {
54+
expect(getLanguageFromPath('file.unknown')).toBe('javascript');
55+
});
56+
57+
it('should return javascript as fallback for files without extension', () => {
58+
expect(getLanguageFromPath('README')).toBe('javascript');
59+
});
60+
61+
it('should handle paths with multiple dots', () => {
62+
expect(getLanguageFromPath('src/components/MyComponent.tsx')).toBe('typescript');
63+
});
64+
65+
it('should handle case insensitive extensions', () => {
66+
expect(getLanguageFromPath('Component.TSX')).toBe('typescript');
67+
expect(getLanguageFromPath('Script.JS')).toBe('javascript');
68+
});
69+
});
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { AvailableLanguagesPrism } from "../SyntaxHighlight/availableLanguagesPrism";
2+
3+
/**
4+
* Maps file extensions to syntax highlighting languages supported by react-syntax-highlighter
5+
*/
6+
export function getLanguageFromPath(filePath: string): AvailableLanguagesPrism {
7+
const extension = filePath.split('.').pop()?.toLowerCase();
8+
9+
switch (extension) {
10+
case 'js':
11+
case 'jsx':
12+
case 'mjs':
13+
case 'cjs':
14+
return 'javascript';
15+
case 'ts':
16+
case 'tsx':
17+
return 'typescript';
18+
case 'py':
19+
case 'python':
20+
return 'python';
21+
case 'java':
22+
return 'java';
23+
case 'cpp':
24+
case 'cc':
25+
case 'cxx':
26+
case 'c++':
27+
return 'cpp';
28+
case 'c':
29+
case 'h':
30+
return 'c';
31+
case 'cs':
32+
return 'csharp';
33+
case 'php':
34+
return 'php';
35+
case 'rb':
36+
case 'ruby':
37+
return 'ruby';
38+
case 'go':
39+
return 'go';
40+
case 'rs':
41+
return 'rust';
42+
case 'swift':
43+
return 'swift';
44+
case 'kt':
45+
case 'kts':
46+
return 'kotlin';
47+
case 'scala':
48+
return 'scala';
49+
case 'sh':
50+
case 'bash':
51+
return 'bash';
52+
case 'ps1':
53+
return 'powershell';
54+
case 'sql':
55+
return 'sql';
56+
case 'html':
57+
case 'htm':
58+
return 'html';
59+
case 'css':
60+
return 'css';
61+
case 'scss':
62+
case 'sass':
63+
return 'scss';
64+
case 'json':
65+
return 'json';
66+
case 'xml':
67+
return 'xml';
68+
case 'yaml':
69+
case 'yml':
70+
return 'yaml';
71+
case 'md':
72+
case 'markdown':
73+
return 'markdown';
74+
case 'dockerfile':
75+
return 'dockerfile';
76+
case 'r':
77+
return 'r';
78+
case 'dart':
79+
return 'dart';
80+
case 'lua':
81+
return 'lua';
82+
case 'perl':
83+
case 'pl':
84+
return 'perl';
85+
case 'vim':
86+
return 'vim';
87+
default:
88+
return 'javascript'; // fallback to javascript for unknown extensions
89+
}
90+
}

0 commit comments

Comments
 (0)