124 lines
3.1 KiB
TypeScript
124 lines
3.1 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { AyuDark } from './ayu.js';
|
|
import { AyuLight } from './ayu-light.js';
|
|
import { AtomOneDark } from './atom-one-dark.js';
|
|
import { Dracula } from './dracula.js';
|
|
import { GitHubDark } from './github-dark.js';
|
|
import { GitHubLight } from './github-light.js';
|
|
import { GoogleCode } from './googlecode.js';
|
|
import { DefaultLight } from './default-light.js';
|
|
import { DefaultDark } from './default.js';
|
|
import { XCode } from './xcode.js';
|
|
import { Theme, ThemeType } from './theme.js';
|
|
import { ANSI } from './ansi.js';
|
|
import { ANSILight } from './ansi-light.js';
|
|
import { NoColorTheme } from './no-color.js';
|
|
import process from 'node:process';
|
|
|
|
export interface ThemeDisplay {
|
|
name: string;
|
|
type: ThemeType;
|
|
}
|
|
|
|
export const DEFAULT_THEME: Theme = DefaultDark;
|
|
|
|
class ThemeManager {
|
|
private readonly availableThemes: Theme[];
|
|
private activeTheme: Theme;
|
|
|
|
constructor() {
|
|
this.availableThemes = [
|
|
AyuDark,
|
|
AyuLight,
|
|
AtomOneDark,
|
|
Dracula,
|
|
DefaultLight,
|
|
DefaultDark,
|
|
GitHubDark,
|
|
GitHubLight,
|
|
GoogleCode,
|
|
XCode,
|
|
ANSI,
|
|
ANSILight,
|
|
];
|
|
this.activeTheme = DEFAULT_THEME;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of available theme names.
|
|
*/
|
|
getAvailableThemes(): ThemeDisplay[] {
|
|
const sortedThemes = [...this.availableThemes].sort((a, b) => {
|
|
const typeOrder = (type: ThemeType): number => {
|
|
switch (type) {
|
|
case 'dark':
|
|
return 1;
|
|
case 'light':
|
|
return 2;
|
|
default:
|
|
return 3;
|
|
}
|
|
};
|
|
|
|
const typeComparison = typeOrder(a.type) - typeOrder(b.type);
|
|
if (typeComparison !== 0) {
|
|
return typeComparison;
|
|
}
|
|
return a.name.localeCompare(b.name);
|
|
});
|
|
|
|
return sortedThemes.map((theme) => ({
|
|
name: theme.name,
|
|
type: theme.type,
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Sets the active theme.
|
|
* @param themeName The name of the theme to activate.
|
|
* @returns True if the theme was successfully set, false otherwise.
|
|
*/
|
|
setActiveTheme(themeName: string | undefined): boolean {
|
|
const foundTheme = this.findThemeByName(themeName);
|
|
|
|
if (foundTheme) {
|
|
this.activeTheme = foundTheme;
|
|
return true;
|
|
} else {
|
|
// If themeName is undefined, it means we want to set the default theme.
|
|
// If findThemeByName returns undefined (e.g. default theme is also not found for some reason)
|
|
// then this will return false.
|
|
if (themeName === undefined) {
|
|
this.activeTheme = DEFAULT_THEME;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
findThemeByName(themeName: string | undefined): Theme | undefined {
|
|
if (!themeName) {
|
|
return DEFAULT_THEME;
|
|
}
|
|
return this.availableThemes.find((theme) => theme.name === themeName);
|
|
}
|
|
|
|
/**
|
|
* Returns the currently active theme object.
|
|
*/
|
|
getActiveTheme(): Theme {
|
|
if (process.env.NO_COLOR) {
|
|
return NoColorTheme;
|
|
}
|
|
return this.activeTheme;
|
|
}
|
|
}
|
|
|
|
// Export an instance of the ThemeManager
|
|
export const themeManager = new ThemeManager();
|