From a46d0ac83755410daa3374bde1db7f241e42f6bd Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Fri, 11 Oct 2024 23:53:24 +0200 Subject: [PATCH 01/20] Add interfaces for themes --- .../model/themes/editor-colors.interface.ts | 28 +++++++++++++++++++ ...nguage-token-style-definition.interface.ts | 27 ++++++++++++++++++ .../monaco-theme-definition.interface.ts | 8 ++++++ 3 files changed, 63 insertions(+) create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/language-token-style-definition.interface.ts create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts new file mode 100644 index 000000000000..bbc66aa43e2a --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts @@ -0,0 +1,28 @@ +/** + * Interface for the colors of the editor. + * See https://code.visualstudio.com/api/references/theme-color + */ +export interface EditorColors { + backgroundColor?: string; // editor.background + foregroundColor?: string; // editor.foreground + lineNumbers?: { + foregroundColor?: string; // editorLineNumber.foreground + activeForegroundColor?: string; // editorLineNumber.activeForeground + dimmedForegroundColor?: string; // editorLineNumber.dimmedForeground + }; + lineHighlight?: { + backgroundColor?: string; // editor.lineHighlightBackground + borderColor?: string; // editor.lineHighlightBorder + }; + diff?: { + insertedLineBackgroundColor?: string; // diffEditor.insertedLineBackground + insertedTextBackgroundColor?: string; // diffEditor.insertedTextBackground + removedTextBackgroundColor?: string; // diffEditor.removedTextBackground + removedLineBackgroundColor?: string; // diffEditor.removedLineBackground + diagonalFillColor?: string; // diffEditor.diagonalFill + gutter?: { + insertedLineBackgroundColor?: string; // diffEditorGutter.insertedLineBackground + removedLineBackgroundColor?: string; // diffEditorGutter.removedLineBackground + }; + }; +} diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/language-token-style-definition.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/language-token-style-definition.interface.ts new file mode 100644 index 000000000000..d811b868ad58 --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/language-token-style-definition.interface.ts @@ -0,0 +1,27 @@ +/** + * Interface for the style of a token in a language. + * The editor applies these styles to the tokens in the specified language (or all languages), e.g. identifiers, keywords, etc. + */ +export interface LanguageTokenStyleDefinition { + /** + * The token to style, e.g. identifier + */ + token: string; + /** + * The language ID for which the token style should be applied. + * If not specified, the style is applied to all languages. + */ + languageId?: string; + /** + * The color of the text that should be applied to the token. + */ + foregroundColor?: string; + /** + * The background color that should be applied to the token. + */ + backgroundColor?: string; + /** + * The font style that should be applied to the token. + */ + fontStyle?: 'italic' | 'bold' | 'underline'; +} diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts new file mode 100644 index 000000000000..55b6f37841b8 --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts @@ -0,0 +1,8 @@ +import { LanguageTokenStyleDefinition } from 'app/shared/monaco-editor/model/themes/language-token-style-definition.interface'; +import { EditorColors } from 'app/shared/monaco-editor/model/themes/editor-colors.interface'; + +export interface MonacoThemeDefinition { + baseTheme: 'vs' | 'vs-dark' | 'hc-light' | 'hc-black'; + tokenStyles: LanguageTokenStyleDefinition[]; + editorColors: EditorColors; +} From dde4081a20d793d95f4b89936e79a0bdbcb1963d Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 00:01:34 +0200 Subject: [PATCH 02/20] Add empty theme definitions --- .../model/themes/monaco-dark.theme.ts | 11 ++++++++++ .../model/themes/monaco-light.theme.ts | 11 ++++++++++ .../model/themes/monaco-theme.model.ts | 18 +++++++++++++++ .../monaco-editor/monaco-editor.service.ts | 22 ++++++++++++++----- 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts create mode 100644 src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts new file mode 100644 index 000000000000..2771760b153e --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -0,0 +1,11 @@ +import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; +import { MonacoEditorService } from 'app/shared/monaco-editor/monaco-editor.service'; + +const themeDefinition: MonacoThemeDefinition = { + baseTheme: 'vs-dark', + tokenStyles: [], // TODO + editorColors: {}, +}; + +export const MONACO_DARK_THEME = new MonacoEditorTheme(MonacoEditorService.DARK_THEME_ID, themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts new file mode 100644 index 000000000000..a3f6eb661e9c --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts @@ -0,0 +1,11 @@ +import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; +import { MonacoEditorService } from 'app/shared/monaco-editor/monaco-editor.service'; + +const themeDefinition: MonacoThemeDefinition = { + baseTheme: 'vs', + tokenStyles: [], // TODO + editorColors: {}, +}; + +export const MONACO_LIGHT_THEME = new MonacoEditorTheme(MonacoEditorService.LIGHT_THEME_ID, themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts new file mode 100644 index 000000000000..5460ed4562ba --- /dev/null +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts @@ -0,0 +1,18 @@ +import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; +import * as monaco from 'monaco-editor'; + +export class MonacoEditorTheme { + constructor( + private readonly id: string, + private readonly themeDefinition: MonacoThemeDefinition, + ) {} + + register(): void { + monaco.editor.defineTheme(this.id, { + base: this.themeDefinition.baseTheme, + inherit: true, + rules: [], + colors: {}, + }); + } +} diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 0d00d81300a3..dd596d6a4566 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -3,6 +3,8 @@ import * as monaco from 'monaco-editor'; import { CUSTOM_MARKDOWN_CONFIG, CUSTOM_MARKDOWN_LANGUAGE, CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { Theme, ThemeService } from 'app/core/theme/theme.service'; import { toSignal } from '@angular/core/rxjs-interop'; +import { MONACO_DARK_THEME } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; +import { MONACO_LIGHT_THEME } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; /** * Service providing shared functionality for the Monaco editor. @@ -11,22 +13,32 @@ import { toSignal } from '@angular/core/rxjs-interop'; */ @Injectable({ providedIn: 'root' }) export class MonacoEditorService { - static readonly LIGHT_THEME_ID = 'vs'; - static readonly DARK_THEME_ID = 'vs-dark'; + static readonly LIGHT_THEME_ID = 'custom-light'; + static readonly DARK_THEME_ID = 'custom-dark'; private readonly themeService: ThemeService = inject(ThemeService); private readonly currentTheme = toSignal(this.themeService.getCurrentThemeObservable(), { requireSync: true }); constructor() { - monaco.languages.register({ id: CUSTOM_MARKDOWN_LANGUAGE_ID }); - monaco.languages.setLanguageConfiguration(CUSTOM_MARKDOWN_LANGUAGE_ID, CUSTOM_MARKDOWN_CONFIG); - monaco.languages.setMonarchTokensProvider(CUSTOM_MARKDOWN_LANGUAGE_ID, CUSTOM_MARKDOWN_LANGUAGE); + this.registerCustomThemes(); + this.registerCustomMarkdownLanguage(); effect(() => { this.applyTheme(this.currentTheme()); }); } + private registerCustomThemes(): void { + MONACO_LIGHT_THEME.register(); + MONACO_DARK_THEME.register(); + } + + private registerCustomMarkdownLanguage(): void { + monaco.languages.register({ id: CUSTOM_MARKDOWN_LANGUAGE_ID }); + monaco.languages.setLanguageConfiguration(CUSTOM_MARKDOWN_LANGUAGE_ID, CUSTOM_MARKDOWN_CONFIG); + monaco.languages.setMonarchTokensProvider(CUSTOM_MARKDOWN_LANGUAGE_ID, CUSTOM_MARKDOWN_LANGUAGE); + } + /** * Applies the given theme to the Monaco editor. * @param artemisTheme The theme to apply. From feb19451ce644df76684d1d9dc2387e902ea1f23 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 00:09:57 +0200 Subject: [PATCH 03/20] Fix error --- .../monaco-editor/model/themes/monaco-dark.theme.ts | 3 +-- .../monaco-editor/model/themes/monaco-light.theme.ts | 3 +-- .../monaco-editor/model/themes/monaco-theme.model.ts | 4 ++++ .../app/shared/monaco-editor/monaco-editor.service.ts | 5 +---- .../shared/monaco-editor/monaco-editor.service.spec.ts | 8 +++++--- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index 2771760b153e..acbcba6c5744 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -1,6 +1,5 @@ import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; -import { MonacoEditorService } from 'app/shared/monaco-editor/monaco-editor.service'; const themeDefinition: MonacoThemeDefinition = { baseTheme: 'vs-dark', @@ -8,4 +7,4 @@ const themeDefinition: MonacoThemeDefinition = { editorColors: {}, }; -export const MONACO_DARK_THEME = new MonacoEditorTheme(MonacoEditorService.DARK_THEME_ID, themeDefinition); +export const MONACO_DARK_THEME = new MonacoEditorTheme('custom-dark', themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts index a3f6eb661e9c..b7e0a299fbc9 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts @@ -1,6 +1,5 @@ import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; -import { MonacoEditorService } from 'app/shared/monaco-editor/monaco-editor.service'; const themeDefinition: MonacoThemeDefinition = { baseTheme: 'vs', @@ -8,4 +7,4 @@ const themeDefinition: MonacoThemeDefinition = { editorColors: {}, }; -export const MONACO_LIGHT_THEME = new MonacoEditorTheme(MonacoEditorService.LIGHT_THEME_ID, themeDefinition); +export const MONACO_LIGHT_THEME = new MonacoEditorTheme('custom-light', themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts index 5460ed4562ba..2705647a88e5 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts @@ -7,6 +7,10 @@ export class MonacoEditorTheme { private readonly themeDefinition: MonacoThemeDefinition, ) {} + getId(): string { + return this.id; + } + register(): void { monaco.editor.defineTheme(this.id, { base: this.themeDefinition.baseTheme, diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index dd596d6a4566..099ecd258673 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -13,9 +13,6 @@ import { MONACO_LIGHT_THEME } from 'app/shared/monaco-editor/model/themes/monaco */ @Injectable({ providedIn: 'root' }) export class MonacoEditorService { - static readonly LIGHT_THEME_ID = 'custom-light'; - static readonly DARK_THEME_ID = 'custom-dark'; - private readonly themeService: ThemeService = inject(ThemeService); private readonly currentTheme = toSignal(this.themeService.getCurrentThemeObservable(), { requireSync: true }); @@ -45,7 +42,7 @@ export class MonacoEditorService { * @private */ private applyTheme(artemisTheme: Theme): void { - monaco.editor.setTheme(artemisTheme === Theme.LIGHT ? MonacoEditorService.LIGHT_THEME_ID : MonacoEditorService.DARK_THEME_ID); + monaco.editor.setTheme(artemisTheme === Theme.LIGHT ? MONACO_LIGHT_THEME.getId() : MONACO_DARK_THEME.getId()); } /** diff --git a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts index 82ffd4e2b8b3..813a15e29c52 100644 --- a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts +++ b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts @@ -6,6 +6,8 @@ import { ArtemisTestModule } from '../../../test.module'; import { CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { BehaviorSubject } from 'rxjs'; import { MockResizeObserver } from '../../../helpers/mocks/service/mock-resize-observer'; +import { MONACO_LIGHT_THEME } from '../../../../../../main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme'; +import { MONACO_DARK_THEME } from '../../../../../../main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme'; describe('MonacoEditorService', () => { let monacoEditorService: MonacoEditorService; @@ -40,17 +42,17 @@ describe('MonacoEditorService', () => { it('should correctly handle themes', () => { // Initialization: The editor should be in light mode since that is what we initialized the themeSubject with - expect(setThemeSpy).toHaveBeenCalledExactlyOnceWith(MonacoEditorService.LIGHT_THEME_ID); + expect(setThemeSpy).toHaveBeenCalledExactlyOnceWith(MONACO_LIGHT_THEME.getId()); // Switch to dark theme themeSubject.next(Theme.DARK); TestBed.flushEffects(); expect(setThemeSpy).toHaveBeenCalledTimes(2); - expect(setThemeSpy).toHaveBeenNthCalledWith(2, MonacoEditorService.DARK_THEME_ID); + expect(setThemeSpy).toHaveBeenNthCalledWith(2, MONACO_DARK_THEME.getId()); // Switch back to light theme themeSubject.next(Theme.LIGHT); TestBed.flushEffects(); expect(setThemeSpy).toHaveBeenCalledTimes(3); - expect(setThemeSpy).toHaveBeenNthCalledWith(3, MonacoEditorService.LIGHT_THEME_ID); + expect(setThemeSpy).toHaveBeenNthCalledWith(3, MONACO_LIGHT_THEME.getId()); }); it.each([ From 2d48289513775f73ee2c10f9e3a57bac3561ae8f Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 01:39:31 +0200 Subject: [PATCH 04/20] Add CSS hacks for line highlighting --- .../monaco-editor/monaco-diff-editor.component.scss | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss index 85f7d08ca87a..2b3e1cc125a5 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss +++ b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss @@ -9,3 +9,14 @@ .diff-hidden-lines .bottom { visibility: hidden; } + +.monaco-editor { + // Prevents the editor from highlighting the entire line with char-insert when the line is new. + .cdr.line-insert[style*='width:100%;'] + .cdr.char-insert[style*='width:100%;'] { + background-color: transparent; + } + // Prevents the editor from highlighting the entire line with char-delete when the line is removed. + .cdr.line-delete[style*='width:100%;'] + .cdr.char-delete[style*='width:100%;'] { + background-color: transparent; + } +} From 14e5dfd5e8b2ccb0da70ede2371f9c2f109398bf Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 01:40:04 +0200 Subject: [PATCH 05/20] Actually apply themes --- .../model/themes/editor-colors.interface.ts | 1 + .../model/themes/monaco-dark.theme.ts | 34 ++++++++++++++- .../model/themes/monaco-theme.model.ts | 42 ++++++++++++++++++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts index bbc66aa43e2a..57b1ace7fed4 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts @@ -1,6 +1,7 @@ /** * Interface for the colors of the editor. * See https://code.visualstudio.com/api/references/theme-color + * All colors must be in the format '#RRGGBB' or '#RRGGBBAA'. */ export interface EditorColors { backgroundColor?: string; // editor.background diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index acbcba6c5744..58b1bc22f845 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -3,8 +3,38 @@ import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco- const themeDefinition: MonacoThemeDefinition = { baseTheme: 'vs-dark', - tokenStyles: [], // TODO - editorColors: {}, + tokenStyles: [ + /*{ + token: 'keyword', + languageId: CUSTOM_MARKDOWN_LANGUAGE_ID, + foregroundColor: '#ffffff', + },*/ + { + token: 'keyword', + foregroundColor: '#ff7b72', + }, + { + token: 'comment', + foregroundColor: '#9198a1', + }, + ], // TODO + editorColors: { + backgroundColor: '#181a18', + lineHighlight: { + borderColor: '#00000000', // TODO bg color + }, + diff: { + insertedLineBackgroundColor: '#2ea04326', + insertedTextBackgroundColor: '#2ea04366', + removedLineBackgroundColor: '#f8514926', + removedTextBackgroundColor: '#f8514966', + diagonalFillColor: '#00000000', + gutter: { + insertedLineBackgroundColor: '#3fb9504d', + removedLineBackgroundColor: '#f851494d', + }, + }, + }, }; export const MONACO_DARK_THEME = new MonacoEditorTheme('custom-dark', themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts index 2705647a88e5..a13ff6eacc6d 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts @@ -11,12 +11,50 @@ export class MonacoEditorTheme { return this.id; } + private stripUndefinedValues(obj: Record): Record { + const result: Record = {}; + for (const [key, value] of Object.entries(obj)) { + if (value !== undefined) { + result[key] = value; + } + } + return result; + } + register(): void { + const colorDefinitions = this.themeDefinition.editorColors; + const colors = { + 'editor.background': colorDefinitions.backgroundColor, + 'editor.foreground': colorDefinitions.foregroundColor, + 'editorLineNumber.foreground': colorDefinitions.lineNumbers?.foregroundColor, + 'editorLineNumber.activeForeground': colorDefinitions.lineNumbers?.activeForegroundColor, + 'editorLineNumber.dimmedForeground': colorDefinitions.lineNumbers?.dimmedForegroundColor, + 'editor.lineHighlightBackground': colorDefinitions.lineHighlight?.backgroundColor, + 'editor.lineHighlightBorder': colorDefinitions.lineHighlight?.borderColor, + 'diffEditor.insertedLineBackground': colorDefinitions.diff?.insertedLineBackgroundColor, + 'diffEditor.insertedTextBackground': colorDefinitions.diff?.insertedTextBackgroundColor, + 'diffEditor.removedTextBackground': colorDefinitions.diff?.removedTextBackgroundColor, + 'diffEditor.removedLineBackground': colorDefinitions.diff?.removedLineBackgroundColor, + 'diffEditor.diagonalFill': colorDefinitions.diff?.diagonalFillColor, + 'diffEditorGutter.insertedLineBackground': colorDefinitions.diff?.gutter?.insertedLineBackgroundColor, + 'diffEditorGutter.removedLineBackground': colorDefinitions.diff?.gutter?.removedLineBackgroundColor, + }; + + const ruleDefinitions = this.themeDefinition.tokenStyles; + const rules = ruleDefinitions.map((rule) => { + return { + token: `${rule.token}${rule.languageId ? '.' + rule.languageId : ''}`, + foreground: rule.foregroundColor, + background: rule.backgroundColor, + fontStyle: rule.fontStyle, + }; + }); + monaco.editor.defineTheme(this.id, { base: this.themeDefinition.baseTheme, inherit: true, - rules: [], - colors: {}, + rules: rules, + colors: this.stripUndefinedValues(colors), }); } } From 14059bb0a272f888004f03c422e2e2c7c74bc40d Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 01:58:46 +0200 Subject: [PATCH 06/20] Fix color hack --- .../shared/monaco-editor/monaco-diff-editor.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss index 2b3e1cc125a5..f1d9a3cccf32 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss +++ b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss @@ -12,11 +12,11 @@ .monaco-editor { // Prevents the editor from highlighting the entire line with char-insert when the line is new. - .cdr.line-insert[style*='width:100%;'] + .cdr.char-insert[style*='width:100%;'] { + .cdr.line-insert[style*='width:100%;'] ~ .cdr.char-insert[style*='width:100%;'] { background-color: transparent; } // Prevents the editor from highlighting the entire line with char-delete when the line is removed. - .cdr.line-delete[style*='width:100%;'] + .cdr.char-delete[style*='width:100%;'] { + .cdr.line-delete[style*='width:100%;'] ~ .cdr.char-delete[style*='width:100%;'] { background-color: transparent; } } From 182413dbe1ae9e717a49b5ef9f6c6663a0ac8df6 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 01:59:01 +0200 Subject: [PATCH 07/20] More color adjustments --- .../model/themes/monaco-dark.theme.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index 58b1bc22f845..cff333a236fd 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -17,11 +17,25 @@ const themeDefinition: MonacoThemeDefinition = { token: 'comment', foregroundColor: '#9198a1', }, + { + token: 'string', + foregroundColor: '#a5d6ff', + }, + { + token: 'number', + foregroundColor: '#79c0ff', + }, ], // TODO editorColors: { backgroundColor: '#181a18', lineHighlight: { borderColor: '#00000000', // TODO bg color + backgroundColor: '#282a2e', + }, + lineNumbers: { + foregroundColor: '#ffffff', + activeForegroundColor: '#ffffff', + dimmedForegroundColor: '#ffffff', }, diff: { insertedLineBackgroundColor: '#2ea04326', From 64b9e36726f49c161d1950ac88eb52bd3aba32e5 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 02:02:41 +0200 Subject: [PATCH 08/20] More dark color adjustments --- .../app/shared/monaco-editor/model/themes/monaco-dark.theme.ts | 2 +- .../webapp/app/shared/monaco-editor/monaco-editor.service.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index cff333a236fd..ddcaabcd1847 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -41,7 +41,7 @@ const themeDefinition: MonacoThemeDefinition = { insertedLineBackgroundColor: '#2ea04326', insertedTextBackgroundColor: '#2ea04366', removedLineBackgroundColor: '#f8514926', - removedTextBackgroundColor: '#f8514966', + removedTextBackgroundColor: '#f8514946', diagonalFillColor: '#00000000', gutter: { insertedLineBackgroundColor: '#3fb9504d', diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 099ecd258673..25233c35afd3 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -87,6 +87,9 @@ export class MonacoEditorService { hideUnchangedRegions: { enabled: true, }, + guides: { + indentation: false, + }, fontSize: 12, }); } From d0e5fb174c28faad0bbc26a7ee3ca181daa6a1a9 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 02:11:25 +0200 Subject: [PATCH 09/20] Make diff less bright --- .../app/shared/monaco-editor/model/themes/monaco-dark.theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index ddcaabcd1847..c48b4243d18c 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -39,7 +39,7 @@ const themeDefinition: MonacoThemeDefinition = { }, diff: { insertedLineBackgroundColor: '#2ea04326', - insertedTextBackgroundColor: '#2ea04366', + insertedTextBackgroundColor: '#2ea04346', removedLineBackgroundColor: '#f8514926', removedTextBackgroundColor: '#f8514946', diagonalFillColor: '#00000000', From ed857adf916adf48d245cdd84719b49e7f79038d Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 10:49:25 +0200 Subject: [PATCH 10/20] Remove color hack --- .../monaco-editor/monaco-diff-editor.component.scss | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss index f1d9a3cccf32..63af0d7c9f68 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss +++ b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss @@ -11,12 +11,5 @@ } .monaco-editor { - // Prevents the editor from highlighting the entire line with char-insert when the line is new. - .cdr.line-insert[style*='width:100%;'] ~ .cdr.char-insert[style*='width:100%;'] { - background-color: transparent; - } - // Prevents the editor from highlighting the entire line with char-delete when the line is removed. - .cdr.line-delete[style*='width:100%;'] ~ .cdr.char-delete[style*='width:100%;'] { - background-color: transparent; - } + outline: none; } From 081d020f7392030c3478fe4987e9fb753fb917b4 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 10:49:40 +0200 Subject: [PATCH 11/20] Disable line highlight --- .../webapp/app/shared/monaco-editor/monaco-editor.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 25233c35afd3..49244f72c8c9 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -90,6 +90,7 @@ export class MonacoEditorService { guides: { indentation: false, }, + renderLineHighlight: 'none', fontSize: 12, }); } From 7e6dfbe505958ea15a6f3b326ae7a3738f1e45f4 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sat, 12 Oct 2024 10:52:06 +0200 Subject: [PATCH 12/20] Basic light theme --- .../model/themes/monaco-light.theme.ts | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts index b7e0a299fbc9..c6326e36b20e 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts @@ -3,8 +3,46 @@ import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco- const themeDefinition: MonacoThemeDefinition = { baseTheme: 'vs', - tokenStyles: [], // TODO - editorColors: {}, + tokenStyles: [ + { + token: 'keyword', + foregroundColor: '#cf222e', + }, + { + token: 'comment', + foregroundColor: '#59636e', + }, + { + token: 'string', + foregroundColor: '#0a3069', + }, + { + token: 'number', + foregroundColor: '#0550ae', + }, + ], + editorColors: { + lineHighlight: { + borderColor: '#00000000', + backgroundColor: '#e8e8e8', + }, + lineNumbers: { + foregroundColor: '#000000', + activeForegroundColor: '#000000', + dimmedForegroundColor: '#000000', + }, + diff: { + insertedLineBackgroundColor: '#dafbe1e6', + insertedTextBackgroundColor: '#aceebbe6', + removedLineBackgroundColor: '#ffebe9ef', + removedTextBackgroundColor: '#ff818250', + diagonalFillColor: '#00000000', + gutter: { + insertedLineBackgroundColor: '#d1f8d9', + removedLineBackgroundColor: '#ffcecb', + }, + }, + }, }; export const MONACO_LIGHT_THEME = new MonacoEditorTheme('custom-light', themeDefinition); From a173188fe0fc11e3195d3bf147745fbe0171b220 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 09:19:17 +0200 Subject: [PATCH 13/20] Adjust dark colors --- .../shared/monaco-editor/model/themes/monaco-dark.theme.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index c48b4243d18c..15edbfbe3b24 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -25,11 +25,11 @@ const themeDefinition: MonacoThemeDefinition = { token: 'number', foregroundColor: '#79c0ff', }, - ], // TODO + ], editorColors: { backgroundColor: '#181a18', lineHighlight: { - borderColor: '#00000000', // TODO bg color + borderColor: '#00000000', backgroundColor: '#282a2e', }, lineNumbers: { @@ -39,7 +39,7 @@ const themeDefinition: MonacoThemeDefinition = { }, diff: { insertedLineBackgroundColor: '#2ea04326', - insertedTextBackgroundColor: '#2ea04346', + insertedTextBackgroundColor: '#2ea04326', removedLineBackgroundColor: '#f8514926', removedTextBackgroundColor: '#f8514946', diagonalFillColor: '#00000000', From 5c1d1a7c3d74b2ed2b43079e066de80735637ef1 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 09:27:21 +0200 Subject: [PATCH 14/20] Move instantiation to service --- .../model/themes/monaco-dark.theme.ts | 11 ++--------- .../model/themes/monaco-light.theme.ts | 6 ++---- .../themes/monaco-theme-definition.interface.ts | 1 + .../model/themes/monaco-theme.model.ts | 9 +++------ .../monaco-editor/monaco-editor.service.ts | 16 +++++++++++----- .../monaco-editor/monaco-editor.service.spec.ts | 10 +++++----- 6 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts index 15edbfbe3b24..24dc4969284e 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme.ts @@ -1,14 +1,9 @@ import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; -import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; -const themeDefinition: MonacoThemeDefinition = { +export const MONACO_DARK_THEME_DEFINITION: MonacoThemeDefinition = { + id: 'custom-dark', baseTheme: 'vs-dark', tokenStyles: [ - /*{ - token: 'keyword', - languageId: CUSTOM_MARKDOWN_LANGUAGE_ID, - foregroundColor: '#ffffff', - },*/ { token: 'keyword', foregroundColor: '#ff7b72', @@ -50,5 +45,3 @@ const themeDefinition: MonacoThemeDefinition = { }, }, }; - -export const MONACO_DARK_THEME = new MonacoEditorTheme('custom-dark', themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts index c6326e36b20e..53d265ab5766 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme.ts @@ -1,7 +1,7 @@ import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; -import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; -const themeDefinition: MonacoThemeDefinition = { +export const MONACO_LIGHT_THEME_DEFINITION: MonacoThemeDefinition = { + id: 'custom-light', baseTheme: 'vs', tokenStyles: [ { @@ -44,5 +44,3 @@ const themeDefinition: MonacoThemeDefinition = { }, }, }; - -export const MONACO_LIGHT_THEME = new MonacoEditorTheme('custom-light', themeDefinition); diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts index 55b6f37841b8..0de6563077a1 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme-definition.interface.ts @@ -2,6 +2,7 @@ import { LanguageTokenStyleDefinition } from 'app/shared/monaco-editor/model/the import { EditorColors } from 'app/shared/monaco-editor/model/themes/editor-colors.interface'; export interface MonacoThemeDefinition { + id: string; baseTheme: 'vs' | 'vs-dark' | 'hc-light' | 'hc-black'; tokenStyles: LanguageTokenStyleDefinition[]; editorColors: EditorColors; diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts index a13ff6eacc6d..f3d632613746 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts @@ -2,13 +2,10 @@ import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/mon import * as monaco from 'monaco-editor'; export class MonacoEditorTheme { - constructor( - private readonly id: string, - private readonly themeDefinition: MonacoThemeDefinition, - ) {} + constructor(private readonly themeDefinition: MonacoThemeDefinition) {} getId(): string { - return this.id; + return this.themeDefinition.id; } private stripUndefinedValues(obj: Record): Record { @@ -50,7 +47,7 @@ export class MonacoEditorTheme { }; }); - monaco.editor.defineTheme(this.id, { + monaco.editor.defineTheme(this.getId(), { base: this.themeDefinition.baseTheme, inherit: true, rules: rules, diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 49244f72c8c9..a8bea9dbc199 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -3,8 +3,9 @@ import * as monaco from 'monaco-editor'; import { CUSTOM_MARKDOWN_CONFIG, CUSTOM_MARKDOWN_LANGUAGE, CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { Theme, ThemeService } from 'app/core/theme/theme.service'; import { toSignal } from '@angular/core/rxjs-interop'; -import { MONACO_DARK_THEME } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; -import { MONACO_LIGHT_THEME } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; +import { MONACO_LIGHT_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; +import { MONACO_DARK_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; /** * Service providing shared functionality for the Monaco editor. @@ -16,6 +17,9 @@ export class MonacoEditorService { private readonly themeService: ThemeService = inject(ThemeService); private readonly currentTheme = toSignal(this.themeService.getCurrentThemeObservable(), { requireSync: true }); + private lightTheme: MonacoEditorTheme; + private darkTheme: MonacoEditorTheme; + constructor() { this.registerCustomThemes(); this.registerCustomMarkdownLanguage(); @@ -26,8 +30,10 @@ export class MonacoEditorService { } private registerCustomThemes(): void { - MONACO_LIGHT_THEME.register(); - MONACO_DARK_THEME.register(); + this.lightTheme = new MonacoEditorTheme(MONACO_LIGHT_THEME_DEFINITION); + this.darkTheme = new MonacoEditorTheme(MONACO_DARK_THEME_DEFINITION); + this.lightTheme.register(); + this.darkTheme.register(); } private registerCustomMarkdownLanguage(): void { @@ -42,7 +48,7 @@ export class MonacoEditorService { * @private */ private applyTheme(artemisTheme: Theme): void { - monaco.editor.setTheme(artemisTheme === Theme.LIGHT ? MONACO_LIGHT_THEME.getId() : MONACO_DARK_THEME.getId()); + monaco.editor.setTheme(artemisTheme === Theme.LIGHT ? this.lightTheme.getId() : this.darkTheme.getId()); } /** diff --git a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts index 813a15e29c52..1a5a59e69436 100644 --- a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts +++ b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts @@ -6,8 +6,8 @@ import { ArtemisTestModule } from '../../../test.module'; import { CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { BehaviorSubject } from 'rxjs'; import { MockResizeObserver } from '../../../helpers/mocks/service/mock-resize-observer'; -import { MONACO_LIGHT_THEME } from '../../../../../../main/webapp/app/shared/monaco-editor/model/themes/monaco-light.theme'; -import { MONACO_DARK_THEME } from '../../../../../../main/webapp/app/shared/monaco-editor/model/themes/monaco-dark.theme'; +import { MONACO_LIGHT_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; +import { MONACO_DARK_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; describe('MonacoEditorService', () => { let monacoEditorService: MonacoEditorService; @@ -42,17 +42,17 @@ describe('MonacoEditorService', () => { it('should correctly handle themes', () => { // Initialization: The editor should be in light mode since that is what we initialized the themeSubject with - expect(setThemeSpy).toHaveBeenCalledExactlyOnceWith(MONACO_LIGHT_THEME.getId()); + expect(setThemeSpy).toHaveBeenCalledExactlyOnceWith(MONACO_LIGHT_THEME_DEFINITION.id); // Switch to dark theme themeSubject.next(Theme.DARK); TestBed.flushEffects(); expect(setThemeSpy).toHaveBeenCalledTimes(2); - expect(setThemeSpy).toHaveBeenNthCalledWith(2, MONACO_DARK_THEME.getId()); + expect(setThemeSpy).toHaveBeenNthCalledWith(2, MONACO_DARK_THEME_DEFINITION.id); // Switch back to light theme themeSubject.next(Theme.LIGHT); TestBed.flushEffects(); expect(setThemeSpy).toHaveBeenCalledTimes(3); - expect(setThemeSpy).toHaveBeenNthCalledWith(3, MONACO_LIGHT_THEME.getId()); + expect(setThemeSpy).toHaveBeenNthCalledWith(3, MONACO_LIGHT_THEME_DEFINITION.id); }); it.each([ From 6a5214b9f46d7c7f55a046afa81a67084adc4a25 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 10:26:16 +0200 Subject: [PATCH 15/20] Rename file; refactor --- .../{monaco-theme.model.ts => monaco-editor-theme.model.ts} | 4 ++-- .../webapp/app/shared/monaco-editor/monaco-editor.service.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/main/webapp/app/shared/monaco-editor/model/themes/{monaco-theme.model.ts => monaco-editor-theme.model.ts} (93%) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts similarity index 93% rename from src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts rename to src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts index f3d632613746..fcbdf31aac70 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts @@ -8,7 +8,7 @@ export class MonacoEditorTheme { return this.themeDefinition.id; } - private stripUndefinedValues(obj: Record): Record { + private removeKeysWithUndefinedValues(obj: Record): Record { const result: Record = {}; for (const [key, value] of Object.entries(obj)) { if (value !== undefined) { @@ -51,7 +51,7 @@ export class MonacoEditorTheme { base: this.themeDefinition.baseTheme, inherit: true, rules: rules, - colors: this.stripUndefinedValues(colors), + colors: this.removeKeysWithUndefinedValues(colors), }); } } diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 6f42a012e6ee..c83734732223 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -4,7 +4,7 @@ import { CUSTOM_MARKDOWN_CONFIG, CUSTOM_MARKDOWN_LANGUAGE, CUSTOM_MARKDOWN_LANGU import { Theme, ThemeService } from 'app/core/theme/theme.service'; import { toSignal } from '@angular/core/rxjs-interop'; import { MONACO_LIGHT_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; -import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-theme.model'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-editor-theme.model'; import { MONACO_DARK_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; /** From 9f85c63729742a853996775b409b0ab7d1408a25 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 10:31:56 +0200 Subject: [PATCH 16/20] Cleanup; add comments --- .../model/themes/monaco-editor-theme.model.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts index fcbdf31aac70..fba7211adf11 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts @@ -20,6 +20,7 @@ export class MonacoEditorTheme { register(): void { const colorDefinitions = this.themeDefinition.editorColors; + // The color keys are available here: https://code.visualstudio.com/api/references/theme-color const colors = { 'editor.background': colorDefinitions.backgroundColor, 'editor.foreground': colorDefinitions.foregroundColor, @@ -37,13 +38,14 @@ export class MonacoEditorTheme { 'diffEditorGutter.removedLineBackground': colorDefinitions.diff?.gutter?.removedLineBackgroundColor, }; - const ruleDefinitions = this.themeDefinition.tokenStyles; - const rules = ruleDefinitions.map((rule) => { + const tokenStyleDefinitions = this.themeDefinition.tokenStyles; + const rules = tokenStyleDefinitions.map((tokenDefinition) => { + // Language-specific tokens have the key `token.languageId`, e.g. keyword.custom-md return { - token: `${rule.token}${rule.languageId ? '.' + rule.languageId : ''}`, - foreground: rule.foregroundColor, - background: rule.backgroundColor, - fontStyle: rule.fontStyle, + token: `${tokenDefinition.token}${tokenDefinition.languageId ? '.' + tokenDefinition.languageId : ''}`, + foreground: tokenDefinition.foregroundColor, + background: tokenDefinition.backgroundColor, + fontStyle: tokenDefinition.fontStyle, }; }); From 5c683cf9cabb6d0ecae76688f3556daa462c4948 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 11:31:34 +0200 Subject: [PATCH 17/20] Add client test --- .../monaco-editor/monaco-editor-theme.spec.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/javascript/spec/component/shared/monaco-editor/monaco-editor-theme.spec.ts diff --git a/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor-theme.spec.ts b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor-theme.spec.ts new file mode 100644 index 000000000000..da4a35cbdf18 --- /dev/null +++ b/src/test/javascript/spec/component/shared/monaco-editor/monaco-editor-theme.spec.ts @@ -0,0 +1,67 @@ +import * as monaco from 'monaco-editor'; +import { EditorColors } from 'app/shared/monaco-editor/model/themes/editor-colors.interface'; +import { LanguageTokenStyleDefinition } from 'app/shared/monaco-editor/model/themes/language-token-style-definition.interface'; +import { MonacoThemeDefinition } from 'app/shared/monaco-editor/model/themes/monaco-theme-definition.interface'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-editor-theme.model'; + +describe('MonacoEditorTheme', () => { + const colorDefinitions: EditorColors = { + backgroundColor: '#181a18', + foregroundColor: '#ffffff', + diff: { + insertedLineBackgroundColor: '#2ea04326', + insertedTextBackgroundColor: '#2ea04326', + removedLineBackgroundColor: undefined, // Explicit undefined to test that it is removed before being passed to Monaco + removedTextBackgroundColor: undefined, + }, + }; + + const tokenStyleDefinitions: LanguageTokenStyleDefinition[] = [ + { + token: 'keyword', + foregroundColor: '#ff7b72', + }, + { + token: 'keyword', + languageId: 'custom-language-id', + foregroundColor: '#ffffff', + }, + ]; + + const themeDefinition: MonacoThemeDefinition = { + id: 'test-theme', + baseTheme: 'vs', + tokenStyles: tokenStyleDefinitions, + editorColors: colorDefinitions, + }; + + it('should correctly register a theme', () => { + const theme = new MonacoEditorTheme(themeDefinition); + const defineThemeSpy = jest.spyOn(monaco.editor, 'defineTheme'); + theme.register(); + expect(defineThemeSpy).toHaveBeenCalledExactlyOnceWith('test-theme', { + base: 'vs', + inherit: true, + rules: [ + { + token: 'keyword', + foreground: '#ff7b72', + background: undefined, + fontStyle: undefined, + }, + { + token: 'keyword.custom-language-id', + foreground: '#ffffff', + background: undefined, + fontStyle: undefined, + }, + ], + colors: { + 'editor.background': '#181a18', + 'editor.foreground': '#ffffff', + 'diffEditor.insertedLineBackground': '#2ea04326', + 'diffEditor.insertedTextBackground': '#2ea04326', + }, + }); + }); +}); From 64c9251463465c15f57b7928bfcaa978c1dad170 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 11:42:31 +0200 Subject: [PATCH 18/20] Add docs --- .../model/themes/editor-colors.interface.ts | 85 ++++++++++++++++--- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts index 57b1ace7fed4..a89139f285ee 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/editor-colors.interface.ts @@ -4,26 +4,83 @@ * All colors must be in the format '#RRGGBB' or '#RRGGBBAA'. */ export interface EditorColors { - backgroundColor?: string; // editor.background - foregroundColor?: string; // editor.foreground + /** + * The background color of the editor. + */ + backgroundColor?: string; + /** + * The default color of all text in the editor, not including syntax highlighting. + */ + foregroundColor?: string; + /** + * Colors for line numbers in the editor. + */ lineNumbers?: { - foregroundColor?: string; // editorLineNumber.foreground - activeForegroundColor?: string; // editorLineNumber.activeForeground - dimmedForegroundColor?: string; // editorLineNumber.dimmedForeground + /** + * The color of the line numbers. + */ + foregroundColor?: string; + /** + * The color of the line number of the line that the cursor is on. + */ + activeForegroundColor?: string; + /** + * The color of the line numbers for dimmed lines. This is used for the final newline of the code. + */ + dimmedForegroundColor?: string; }; + /** + * Colors for the active line highlight in the editor. + */ lineHighlight?: { - backgroundColor?: string; // editor.lineHighlightBackground - borderColor?: string; // editor.lineHighlightBorder + /** + * The color used as the background color for the cursor's current line. + */ + backgroundColor?: string; + /** + * The color used for the border of the cursor's current line. + */ + borderColor?: string; }; + /** + * Colors for the diff editor. + */ diff?: { - insertedLineBackgroundColor?: string; // diffEditor.insertedLineBackground - insertedTextBackgroundColor?: string; // diffEditor.insertedTextBackground - removedTextBackgroundColor?: string; // diffEditor.removedTextBackground - removedLineBackgroundColor?: string; // diffEditor.removedLineBackground - diagonalFillColor?: string; // diffEditor.diagonalFill + /** + * The background color for inserted lines in the diff editor. + */ + insertedLineBackgroundColor?: string; + /** + * The background color for inserted text in the diff editor. + * This will overlap with the `insertedLineBackgroundColor`. + */ + insertedTextBackgroundColor?: string; + /** + * The background color for removed lines in the diff editor. + */ + removedTextBackgroundColor?: string; + /** + * The background color for removed text in the diff editor. + * This will overlap with the `removedLineBackgroundColor`. + */ + removedLineBackgroundColor?: string; + /** + * The color used for the diagonal fill in the diff editor. + * This is used when the diff editor pads the length of the files to align the lines of the original and modified files. + */ + diagonalFillColor?: string; + /** + * Colors for the diff editor gutter. This is the area to the left of the editor that shows the line numbers. + */ gutter?: { - insertedLineBackgroundColor?: string; // diffEditorGutter.insertedLineBackground - removedLineBackgroundColor?: string; // diffEditorGutter.removedLineBackground + /** + * The background color for inserted lines in the diff editor gutter. + */ + insertedLineBackgroundColor?: string; + /** + * The background color for removed lines in the diff editor gutter. + */ + removedLineBackgroundColor?: string; }; }; } From a6d0791b768207d1a115157e9f64d1c79706646e Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 11:54:23 +0200 Subject: [PATCH 19/20] Add more docs --- .../model/themes/monaco-editor-theme.model.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts index fba7211adf11..c9f34f06b3de 100644 --- a/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts +++ b/src/main/webapp/app/shared/monaco-editor/model/themes/monaco-editor-theme.model.ts @@ -8,9 +8,15 @@ export class MonacoEditorTheme { return this.themeDefinition.id; } - private removeKeysWithUndefinedValues(obj: Record): Record { + /** + * Creates a new record without any entries that have a value of `undefined`. + * @param record The record whose keys to filter. + * @returns The new record, only containing keys with defined values. + * @private + */ + private getRecordWithoutUndefinedEntries(record: Record): Record { const result: Record = {}; - for (const [key, value] of Object.entries(obj)) { + for (const [key, value] of Object.entries(record)) { if (value !== undefined) { result[key] = value; } @@ -49,11 +55,12 @@ export class MonacoEditorTheme { }; }); + // We cannot pass undefined colors to Monaco, so we filter them out to preserve the default values. monaco.editor.defineTheme(this.getId(), { base: this.themeDefinition.baseTheme, inherit: true, rules: rules, - colors: this.removeKeysWithUndefinedValues(colors), + colors: this.getRecordWithoutUndefinedEntries(colors), }); } } From 814e38dc84a0072fac2d55d14bdf882c1d77da90 Mon Sep 17 00:00:00 2001 From: Patrik Zander Date: Sun, 13 Oct 2024 11:55:08 +0200 Subject: [PATCH 20/20] Move redundant style --- .../shared/monaco-editor/monaco-diff-editor.component.scss | 4 ---- .../app/shared/monaco-editor/monaco-editor.component.scss | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss index 2dd90ab4c538..34b221d82d90 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss +++ b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.scss @@ -18,7 +18,3 @@ .diff-hidden-lines .bottom { visibility: hidden; } - -.monaco-editor { - outline: none; -} diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.scss b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.scss index 96f11784298f..6886fcfcc0dc 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.scss +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.scss @@ -3,6 +3,11 @@ .monaco-editor-container { width: 100%; height: 100%; + + .monaco-editor { + // Disables the focus border around the editor. + outline: none; + } } /*