Skip to content

Commit 8936a95

Browse files
authored
Unified and context diff syntax highlighting (#26)
1 parent 60c1595 commit 8936a95

File tree

5 files changed

+105
-50
lines changed

5 files changed

+105
-50
lines changed

src/components/EditorTextArea.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import themes, { Theme } from '../style/themes';
1717

1818
import type { editor } from 'monaco-editor';
1919
import { ResetFunction } from './Editor';
20-
import { logLanguage } from '../util/log-language';
20+
import { logLanguage } from '../util/languages/log';
21+
import { diffLanguage } from '../util/languages/diff';
2122

2223
import * as monaco from 'monaco-editor';
2324
import { loader } from '@monaco-editor/react';
@@ -68,6 +69,8 @@ export default function EditorTextArea({
6869

6970
monaco.languages.register({ id: 'log' });
7071
monaco.languages.setMonarchTokensProvider('log', logLanguage);
72+
monaco.languages.register({ id: 'diff' });
73+
monaco.languages.setMonarchTokensProvider('diff', diffLanguage);
7174

7275
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
7376
noSemanticValidation: true,

src/style/themes.ts

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ const themes: Themes = {
6464
logWarning: '#d29922', // yellow.3
6565
logDate: '#33B3AE', // teal.3
6666
logException: '#f8e3a1', // yellow.0
67+
diffMeta: '#33B3AE', // teal.3
68+
diffAddition: '#3fb950', // green.3
69+
diffDeletion: '#f85149', // red.4
6770
},
6871
}),
6972
},
@@ -100,6 +103,9 @@ const themes: Themes = {
100103
logWarning: '#d4a72c', // yellow.3
101104
logDate: '#136061', // teal.6
102105
logException: '#7d4e00', // yellow.6
106+
diffMeta: '#136061', // teal.6
107+
diffAddition: '#2da44e', // green.4
108+
diffDeletion: '#cf222e', // red.5
103109
},
104110
}),
105111
},
@@ -114,12 +120,15 @@ const themes: Themes = {
114120
color: '#586e75',
115121
backgroundColor: '#44475a',
116122
},
117-
editor: addLogColors(dracula as editor.IStandaloneThemeData, {
118-
info: '#50FA7B', // green
119-
error: '#FF5555', // red
120-
warning: '#FFB86C', // orange
121-
date: '#BD93F9', // purple
122-
exception: '#F1FA8C', // yellow
123+
editor: addExtraColors(dracula as editor.IStandaloneThemeData, {
124+
logInfo: '#50FA7B', // green
125+
logError: '#FF5555', // red
126+
logWarning: '#FFB86C', // orange
127+
logDate: '#BD93F9', // purple
128+
logException: '#F1FA8C', // yellow
129+
diffMeta: '#BD93F9', // purple
130+
diffAddition: '#50FA7B', // green
131+
diffDeletion: '#FF5555', // red
123132
}),
124133
},
125134
'monokai': {
@@ -133,12 +142,15 @@ const themes: Themes = {
133142
color: '#49483E',
134143
backgroundColor: '#3E3D32',
135144
},
136-
editor: addLogColors(monokai as editor.IStandaloneThemeData, {
137-
info: '#a6e22e', // green
138-
error: '#f92672', // red
139-
warning: '#fd971f', // orange
140-
date: '#AB9DF2', // purple
141-
exception: '#F1FA8C', // yellow
145+
editor: addExtraColors(monokai as editor.IStandaloneThemeData, {
146+
logInfo: '#a6e22e', // green
147+
logError: '#f92672', // red
148+
logWarning: '#fd971f', // orange
149+
logDate: '#AB9DF2', // purple
150+
logException: '#F1FA8C', // yellow
151+
diffMeta: '#AB9DF2', // purple
152+
diffAddition: '#a6e22e', // green
153+
diffDeletion: '#f92672', // red
142154
}),
143155
},
144156
'solarized': {
@@ -152,12 +164,15 @@ const themes: Themes = {
152164
color: '#93a1a1', // base1
153165
backgroundColor: '#073642', // base02
154166
},
155-
editor: addLogColors(solarizedDark as editor.IStandaloneThemeData, {
156-
info: '#268bd2', // blue
157-
error: '#dc322f', // red
158-
warning: '#b58900', // yellow
159-
date: '#2aa198', // cyan
160-
exception: '#859900', // green
167+
editor: addExtraColors(solarizedDark as editor.IStandaloneThemeData, {
168+
logInfo: '#268bd2', // blue
169+
logError: '#dc322f', // red
170+
logWarning: '#b58900', // yellow
171+
logDate: '#2aa198', // cyan
172+
logException: '#859900', // green
173+
diffMeta: '#2aa198', // cyan
174+
diffAddition: '#859900', // green
175+
diffDeletion: '#dc322f', // red
161176
}),
162177
},
163178
'solarized-light': {
@@ -171,18 +186,32 @@ const themes: Themes = {
171186
color: '#586e75', // base01
172187
backgroundColor: '#eee8d5', // base2
173188
},
174-
editor: addLogColors(solarizedLight as editor.IStandaloneThemeData, {
175-
info: '#268bd2', // blue
176-
error: '#dc322f', // red
177-
warning: '#b58900', // yellow
178-
date: '#2aa198', // cyan
179-
exception: '#859900', // green
189+
editor: addExtraColors(solarizedLight as editor.IStandaloneThemeData, {
190+
logInfo: '#268bd2', // blue
191+
logError: '#dc322f', // red
192+
logWarning: '#b58900', // yellow
193+
logDate: '#2aa198', // cyan
194+
logException: '#859900', // green
195+
diffMeta: '#2aa198', // cyan
196+
diffAddition: '#859900', // green
197+
diffDeletion: '#dc322f', // red
180198
}),
181199
},
182200
};
183201

184202
export default themes;
185203

204+
interface ExtraColors {
205+
logInfo: Color;
206+
logError: Color;
207+
logWarning: Color;
208+
logDate: Color;
209+
logException: Color;
210+
diffMeta: Color;
211+
diffAddition: Color;
212+
diffDeletion: Color;
213+
}
214+
186215
interface MonacoThemeProps {
187216
base: 'vs' | 'vs-dark';
188217
colors: {
@@ -198,12 +227,7 @@ interface MonacoThemeProps {
198227
keyword: Color;
199228
type: Color;
200229
variable: Color;
201-
logInfo: Color;
202-
logError: Color;
203-
logWarning: Color;
204-
logDate: Color;
205-
logException: Color;
206-
};
230+
} & ExtraColors;
207231
}
208232

209233
export function makeMonacoTheme(
@@ -246,6 +270,9 @@ export function makeMonacoTheme(
246270
{ token: 'warning.log', foreground: colors.logWarning },
247271
{ token: 'date.log', foreground: colors.logDate },
248272
{ token: 'exception.log', foreground: colors.logException },
273+
{ token: 'meta.diff', foreground: colors.diffMeta },
274+
{ token: 'addition.diff', foreground: colors.diffAddition },
275+
{ token: 'deletion.diff', foreground: colors.diffDeletion },
249276
],
250277
colors: {
251278
'editor.background': `#${colors.background}`,
@@ -254,28 +281,23 @@ export function makeMonacoTheme(
254281
};
255282
}
256283

257-
interface LogColors {
258-
info: Color;
259-
error: Color;
260-
warning: Color;
261-
date: Color;
262-
exception: Color;
263-
}
264-
265-
export function addLogColors(
284+
export function addExtraColors(
266285
theme: editor.IStandaloneThemeData,
267-
logColors: LogColors
286+
extraColors: ExtraColors
268287
): editor.IStandaloneThemeData {
269288
const colors = Object.fromEntries(
270-
Object.entries(logColors).map(([key, color]) => [key, color.substring(1)])
271-
) as Record<keyof LogColors, string>;
289+
Object.entries(extraColors).map(([key, color]) => [key, color.substring(1)])
290+
) as Record<keyof ExtraColors, string>;
272291
theme.rules.push(
273292
...[
274-
{ token: 'info.log', foreground: colors.info },
275-
{ token: 'error.log', foreground: colors.error, fontStyle: 'bold' },
276-
{ token: 'warning.log', foreground: colors.warning },
277-
{ token: 'date.log', foreground: colors.date },
278-
{ token: 'exception.log', foreground: colors.exception },
293+
{ token: 'info.log', foreground: colors.logInfo },
294+
{ token: 'error.log', foreground: colors.logError, fontStyle: 'bold' },
295+
{ token: 'warning.log', foreground: colors.logWarning },
296+
{ token: 'date.log', foreground: colors.logDate },
297+
{ token: 'exception.log', foreground: colors.logException },
298+
{ token: 'meta.diff', foreground: colors.diffMeta },
299+
{ token: 'addition.diff', foreground: colors.diffAddition },
300+
{ token: 'deletion.diff', foreground: colors.diffDeletion },
279301
]
280302
);
281303
return theme;

src/util/highlighting.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ export const languages = {
1717
'go',
1818
'lua',
1919
'swift',
20-
'c'
20+
'c',
2121
],
2222
web: ['html', 'css', 'scss', 'php', 'graphql'],
23-
misc: ['dockerfile', 'markdown', 'proto'],
23+
misc: ['diff', 'dockerfile', 'markdown', 'proto'],
2424
};
2525

2626
export const languageIds = Object.values(languages).flat(1);

src/util/languages/diff.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { languages } from 'monaco-editor';
2+
3+
export const diffLanguage: languages.IMonarchLanguage = {
4+
defaultToken: '',
5+
tokenizer: {
6+
root: [
7+
// Meta lines (e.g., @@ -1,2 +3,4 @@)
8+
[/@@@ +-\d+,\d+ +\+\d+,\d+ +@@@/, 'meta'],
9+
[/^\*\*\* +\d+,\d+ +\*\*\*\*$/, 'meta'],
10+
[/^--- +\d+,\d+ +----$/, 'meta'],
11+
12+
// Comments
13+
[/Index: .*/, 'comment'],
14+
[/^index.*/, 'comment'],
15+
[/={3,}/, 'comment'],
16+
[/^-{3}.*/, 'comment'],
17+
[/^\*{3} .*/, 'comment'],
18+
[/^\+{3}.*/, 'comment'],
19+
[/^diff --git.*/, 'comment'],
20+
[/^\*{15}$/, 'comment'],
21+
22+
// Additions
23+
[/^\+.*/, 'addition'],
24+
[/^!.*/, 'addition'],
25+
26+
// Deletions
27+
[/^-.*/, 'deletion'],
28+
],
29+
},
30+
};

0 commit comments

Comments
 (0)