themeConfig.ts

  1import { Scale, Color } from "chroma-js"
  2import { Syntax } from "./themes/common/syntax"
  3
  4interface ThemeMeta {
  5    /** The name of the theme */
  6    name: string
  7    /** The theme's appearance. Either `light` or `dark`. */
  8    appearance: ThemeAppearance
  9    /** The author of the theme
 10     *
 11     * Ideally formatted as `Full Name <email>`
 12     *
 13     * Example: `John Doe <john@doe.com>`
 14     */
 15    author: string
 16    /** SPDX License string
 17     *
 18     * Example: `MIT`
 19     */
 20    licenseType?: string | ThemeLicenseType
 21    licenseUrl?: string
 22    licenseFile: string
 23    themeUrl?: string
 24}
 25
 26export interface ThemeConfigInputColors {
 27    neutral: Scale<Color>
 28    red: Scale<Color>
 29    orange: Scale<Color>
 30    yellow: Scale<Color>
 31    green: Scale<Color>
 32    cyan: Scale<Color>
 33    blue: Scale<Color>
 34    violet: Scale<Color>
 35    magenta: Scale<Color>
 36}
 37
 38export type ThemeConfigInputColorsKeys = keyof ThemeConfigInputColors
 39
 40/** Allow any part of a syntax highlight style to be overriden by the theme
 41 *
 42 * Example:
 43 * ```ts
 44 * override: {
 45 *   syntax: {
 46 *     boolean: {
 47 *       underline: true,
 48 *     },
 49 *   },
 50 * }
 51 * ```
 52 */
 53export type ThemeConfigInputSyntax = Partial<Syntax>
 54
 55interface ThemeConfigOverrides {
 56    syntax: ThemeConfigInputSyntax
 57}
 58
 59type ThemeConfigProperties = ThemeMeta & {
 60    inputColor: ThemeConfigInputColors
 61    override: ThemeConfigOverrides
 62}
 63
 64// This should be the format a theme is defined as
 65export type ThemeConfig = {
 66    [K in keyof ThemeConfigProperties]: ThemeConfigProperties[K]
 67}
 68
 69interface ThemeColors {
 70    neutral: string[]
 71    red: string[]
 72    orange: string[]
 73    yellow: string[]
 74    green: string[]
 75    cyan: string[]
 76    blue: string[]
 77    violet: string[]
 78    magenta: string[]
 79}
 80
 81type ThemeSyntax = Required<Syntax>
 82
 83export type ThemeProperties = ThemeMeta & {
 84    color: ThemeColors
 85    syntax: ThemeSyntax
 86}
 87
 88// This should be a theme after all its properties have been resolved
 89export type Theme = {
 90    [K in keyof ThemeProperties]: ThemeProperties[K]
 91}
 92
 93export enum ThemeAppearance {
 94    Light = "light",
 95    Dark = "dark",
 96}
 97
 98export enum ThemeLicenseType {
 99    MIT = "MIT",
100    Apache2 = "Apache License 2.0",
101}
102
103export type ThemeFamilyItem =
104    | ThemeConfig
105    | { light: ThemeConfig; dark: ThemeConfig }
106
107type ThemeFamilyProperties = Partial<Omit<ThemeMeta, "name" | "appearance">> & {
108    name: string
109    default: ThemeFamilyItem
110    variants: {
111        [key: string]: ThemeFamilyItem
112    }
113}
114
115// Idea: A theme family is a collection of themes that share the same name
116// For example, a theme family could be `One Dark` and have a `light` and `dark` variant
117// The Ayu family could have `light`, `mirage`, and `dark` variants
118
119type ThemeFamily = {
120    [K in keyof ThemeFamilyProperties]: ThemeFamilyProperties[K]
121}
122
123/** The collection of all themes
124 *
125 * Example:
126 * ```ts
127 * {
128 *   one_dark,
129 *   one_light,
130 *     ayu: {
131 *     name: 'Ayu',
132 *     default: 'ayu_mirage',
133 *     variants: {
134 *       light: 'ayu_light',
135 *       mirage: 'ayu_mirage',
136 *       dark: 'ayu_dark',
137 *     },
138 *   },
139 *  ...
140 * }
141 * ```
142 */
143export type ThemeIndex = Record<string, ThemeFamily | ThemeConfig>