/* eslint-disable @typescript-eslint/no-explicit-any */ import { injectable } from 'inversify'; import { MonacoColorRegistry } from '../common/monaco-color-registry'; import { Color } from '../common/color'; import IColorTheme = MonacoColorRegistry.IColorTheme; import ColorFunction = MonacoColorRegistry.ColorFunction; export type ThemeType = 'light' | 'dark' | 'hc'; export interface ThemeData { name: string, base: string, inherit: boolean, colors: Record, rules: any[] settings: any[] } @injectable() export class MonacoThemeRegistry { protected themes: Record = {}; protected colorThemes: Record = {}; /** * Register VS Code compatible themes */ register(json: any, includes?: { [includePath: string]: any }, givenName?: string, monacoBase?: string): ThemeData { const name = givenName || json.name!; const result: ThemeData = { name, base: monacoBase || 'vs', inherit: true, colors: {}, rules: [], settings: [] }; if (typeof json.include !== 'undefined') { if (!includes || !includes[json.include]) { console.error(`Couldn't resolve includes theme ${json.include}.`); } else { const parentTheme = this.register(includes[json.include], includes); Object.assign(result.colors, parentTheme.colors); result.rules.push(...parentTheme.rules); result.settings.push(...parentTheme.settings); } } if (json.colors) { Object.assign(result.colors, json.colors); // result.encodedTokensColors = Object.keys(result.colors).map(key => result.colors[key]) } this.themes[name] = result; return result; } getColorTheme(type: ThemeType): IColorTheme { const themeData = this.themes[type + '-theia']; if (this.colorThemes[type]) { return this.colorThemes[type]; } const currentTheme = this.colorThemes[type] = { type, getColor(id: string): Color | undefined { if (themeData) { if (themeData.colors[id]) { return Color.fromHex(themeData.colors[id]); } const color = MonacoColorRegistry.getColorRegistry().getColorContribution(id); if (color && color.defaults) { const colorValue = color.defaults[type]; if (typeof colorValue === 'string') { if (colorValue[0] === '#') { return Color.fromHex(colorValue as string); } return currentTheme.getColor(colorValue); } if (typeof colorValue === 'function') { return (colorValue as ColorFunction)(currentTheme); } return colorValue as Color; } } } }; return currentTheme; } protected transform(tokenColor: any, acceptor: (rule: any) => void): void { if (typeof tokenColor.scope === 'undefined') { tokenColor.scope = ['']; } else if (typeof tokenColor.scope === 'string') { tokenColor.scope = tokenColor.scope.split(',').map((scope: string) => scope.trim()); } for (const scope of tokenColor.scope) { acceptor({ ...tokenColor.settings, token: scope }); } } protected normalizeColor(color: string): string | undefined { if (!color) { return undefined; } const normalized = String(color).replace(/^\#/, '').slice(0, 6); if (normalized.length < 6) { // ignoring not normalized colors to avoid breaking token color indexes between monaco and vscode-textmate console.error(`Color '${normalized}' is NOT normalized, it must have 6 positions.`); return undefined; } return '#' + normalized; } } export namespace MonacoThemeRegistry { export const SINGLETON = new MonacoThemeRegistry(); export const DARK_DEFAULT_THEME: ThemeData = SINGLETON.register(require('../../data/monaco-themes/vscode/dark_theia.json'), { './dark_defaults.json': require('../../data/monaco-themes/vscode/dark_defaults.json'), './dark_vs.json': require('../../data/monaco-themes/vscode/dark_vs.json'), './dark_plus.json': require('../../data/monaco-themes/vscode/dark_plus.json') }, 'dark-theia', 'vs-dark'); export const LIGHT_DEFAULT_THEME: ThemeData = SINGLETON.register(require('../../data/monaco-themes/vscode/light_theia.json'), { './light_defaults.json': require('../../data/monaco-themes/vscode/light_defaults.json'), './light_vs.json': require('../../data/monaco-themes/vscode/light_vs.json'), './light_plus.json': require('../../data/monaco-themes/vscode/light_plus.json'), }, 'light-theia', 'vs'); export const HC_DEFAULT_THEME: ThemeData = SINGLETON.register(require('../../data/monaco-themes/vscode/hc_theia.json'), { './hc_black_defaults.json': require('../../data/monaco-themes/vscode/hc_black_defaults.json'), './hc_black.json': require('../../data/monaco-themes/vscode/hc_black.json') }, 'hc-theia', 'hc-black'); }