diff --git a/packages/tui/src/context/theme.tsx b/packages/tui/src/context/theme.tsx index 19fbeb6ec6..3a456fbafc 100644 --- a/packages/tui/src/context/theme.tsx +++ b/packages/tui/src/context/theme.tsx @@ -62,12 +62,9 @@ export { allThemes, generateSyntax, hasTheme, - isTheme, - resolveTheme, selectedForeground, upsertTheme, type Theme, - type ThemeJson, } from "../theme" const THEME_REFRESH_DELAYS = [250, 1000] as const diff --git a/packages/tui/src/theme/index.ts b/packages/tui/src/theme/index.ts index 36263febae..73f12bd16b 100644 --- a/packages/tui/src/theme/index.ts +++ b/packages/tui/src/theme/index.ts @@ -1,167 +1,8 @@ -import { SyntaxStyle, RGBA } from "@opentui/core" +import { RGBA } from "@opentui/core" import { ansiToRgba } from "./color" -import aura from "./assets/aura.json" with { type: "json" } -import ayu from "./assets/ayu.json" with { type: "json" } -import carbonfox from "./assets/carbonfox.json" with { type: "json" } -import catppuccinFrappe from "./assets/catppuccin-frappe.json" with { type: "json" } -import catppuccinMacchiato from "./assets/catppuccin-macchiato.json" with { type: "json" } -import catppuccin from "./assets/catppuccin.json" with { type: "json" } -import cobalt2 from "./assets/cobalt2.json" with { type: "json" } -import cursor from "./assets/cursor.json" with { type: "json" } -import dracula from "./assets/dracula.json" with { type: "json" } -import everforest from "./assets/everforest.json" with { type: "json" } -import flexoki from "./assets/flexoki.json" with { type: "json" } -import github from "./assets/github.json" with { type: "json" } -import gruvbox from "./assets/gruvbox.json" with { type: "json" } -import kanagawa from "./assets/kanagawa.json" with { type: "json" } -import lucentOrng from "./assets/lucent-orng.json" with { type: "json" } -import material from "./assets/material.json" with { type: "json" } -import matrix from "./assets/matrix.json" with { type: "json" } -import mercury from "./assets/mercury.json" with { type: "json" } -import monokai from "./assets/monokai.json" with { type: "json" } -import nightowl from "./assets/nightowl.json" with { type: "json" } -import nord from "./assets/nord.json" with { type: "json" } -import onedark from "./assets/one-dark.json" with { type: "json" } -import opencode from "./assets/opencode.json" with { type: "json" } -import orng from "./assets/orng.json" with { type: "json" } -import osakaJade from "./assets/osaka-jade.json" with { type: "json" } -import palenight from "./assets/palenight.json" with { type: "json" } -import rosepine from "./assets/rosepine.json" with { type: "json" } -import solarized from "./assets/solarized.json" with { type: "json" } -import synthwave84 from "./assets/synthwave84.json" with { type: "json" } -import tokyonight from "./assets/tokyonight.json" with { type: "json" } -import vercel from "./assets/vercel.json" with { type: "json" } -import vesper from "./assets/vesper.json" with { type: "json" } -import zenburn from "./assets/zenburn.json" with { type: "json" } +import { DEFAULT_THEMES, type ColorValue, type Theme, type ThemeColor, type ThemeJson } from "./v1" -export type Theme = { - readonly primary: RGBA - readonly secondary: RGBA - readonly accent: RGBA - readonly error: RGBA - readonly warning: RGBA - readonly success: RGBA - readonly info: RGBA - readonly text: RGBA - readonly textMuted: RGBA - readonly selectedListItemText: RGBA - readonly background: RGBA - readonly backgroundPanel: RGBA - readonly backgroundElement: RGBA - readonly backgroundMenu: RGBA - readonly border: RGBA - readonly borderActive: RGBA - readonly borderSubtle: RGBA - readonly diffAdded: RGBA - readonly diffRemoved: RGBA - readonly diffContext: RGBA - readonly diffHunkHeader: RGBA - readonly diffHighlightAdded: RGBA - readonly diffHighlightRemoved: RGBA - readonly diffAddedBg: RGBA - readonly diffRemovedBg: RGBA - readonly diffContextBg: RGBA - readonly diffLineNumber: RGBA - readonly diffAddedLineNumberBg: RGBA - readonly diffRemovedLineNumberBg: RGBA - readonly markdownText: RGBA - readonly markdownHeading: RGBA - readonly markdownLink: RGBA - readonly markdownLinkText: RGBA - readonly markdownCode: RGBA - readonly markdownBlockQuote: RGBA - readonly markdownEmph: RGBA - readonly markdownStrong: RGBA - readonly markdownHorizontalRule: RGBA - readonly markdownListItem: RGBA - readonly markdownListEnumeration: RGBA - readonly markdownImage: RGBA - readonly markdownImageText: RGBA - readonly markdownCodeBlock: RGBA - readonly syntaxComment: RGBA - readonly syntaxKeyword: RGBA - readonly syntaxFunction: RGBA - readonly syntaxVariable: RGBA - readonly syntaxString: RGBA - readonly syntaxNumber: RGBA - readonly syntaxType: RGBA - readonly syntaxOperator: RGBA - readonly syntaxPunctuation: RGBA - readonly thinkingOpacity: number - _hasSelectedListItemText: boolean -} -type ThemeColor = Exclude - -export function selectedForeground(theme: Theme, bg?: RGBA): RGBA { - // If theme explicitly defines selectedListItemText, use it - if (theme._hasSelectedListItemText) { - return theme.selectedListItemText - } - - // For transparent backgrounds, calculate contrast based on the actual bg (or fallback to primary) - if (theme.background.a === 0) { - const targetColor = bg ?? theme.primary - const { r, g, b } = targetColor - const luminance = 0.299 * r + 0.587 * g + 0.114 * b - return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) - } - - // Fall back to background color - return theme.background -} - -type HexColor = `#${string}` -type RefName = string -type Variant = { - dark: HexColor | RefName - light: HexColor | RefName -} -type ColorValue = HexColor | RefName | Variant | RGBA -export type ThemeJson = { - $schema?: string - defs?: Record - theme: Omit, "selectedListItemText" | "backgroundMenu"> & { - selectedListItemText?: ColorValue - backgroundMenu?: ColorValue - thinkingOpacity?: number - } -} - -export const DEFAULT_THEMES: Record = { - aura, - ayu, - catppuccin, - ["catppuccin-frappe"]: catppuccinFrappe, - ["catppuccin-macchiato"]: catppuccinMacchiato, - cobalt2, - cursor, - dracula, - everforest, - flexoki, - github, - gruvbox, - kanagawa, - material, - matrix, - mercury, - monokai, - nightowl, - nord, - ["one-dark"]: onedark, - ["osaka-jade"]: osakaJade, - opencode, - orng, - ["lucent-orng"]: lucentOrng, - palenight, - rosepine, - solarized, - synthwave84, - tokyonight, - vesper, - vercel, - zenburn, - carbonfox, -} +export { DEFAULT_THEMES, generateSyntax, selectedForeground, type Theme, type ThemeJson } from "./v1" const pluginThemes: Record = {} let customThemes: Record = {} @@ -297,506 +138,3 @@ export function resolveTheme(theme: ThemeJson, mode: "dark" | "light") { thinkingOpacity, } as Theme } - -export function generateSyntax(theme: Theme) { - return SyntaxStyle.fromTheme(getSyntaxRules(theme)) -} - -function getSyntaxRules(theme: Theme) { - return [ - { - scope: ["default"], - style: { - foreground: theme.text, - }, - }, - { - scope: ["prompt"], - style: { - foreground: theme.accent, - }, - }, - { - scope: ["extmark.file"], - style: { - foreground: theme.warning, - bold: true, - }, - }, - { - scope: ["extmark.agent"], - style: { - foreground: theme.secondary, - bold: true, - }, - }, - { - scope: ["extmark.paste"], - style: { - foreground: selectedForeground(theme, theme.warning), - background: theme.warning, - bold: true, - }, - }, - { - scope: ["comment"], - style: { - foreground: theme.syntaxComment, - italic: true, - }, - }, - { - scope: ["comment.documentation"], - style: { - foreground: theme.syntaxComment, - italic: true, - }, - }, - { - scope: ["string", "symbol"], - style: { - foreground: theme.syntaxString, - }, - }, - { - scope: ["number", "boolean"], - style: { - foreground: theme.syntaxNumber, - }, - }, - { - scope: ["character.special"], - style: { - foreground: theme.syntaxString, - }, - }, - { - scope: ["keyword.return", "keyword.conditional", "keyword.repeat", "keyword.coroutine"], - style: { - foreground: theme.syntaxKeyword, - italic: true, - }, - }, - { - scope: ["keyword.type"], - style: { - foreground: theme.syntaxType, - bold: true, - italic: true, - }, - }, - { - scope: ["keyword.function", "function.method"], - style: { - foreground: theme.syntaxFunction, - }, - }, - { - scope: ["keyword"], - style: { - foreground: theme.syntaxKeyword, - italic: true, - }, - }, - { - scope: ["keyword.import"], - style: { - foreground: theme.syntaxKeyword, - }, - }, - { - scope: ["operator", "keyword.operator", "punctuation.delimiter"], - style: { - foreground: theme.syntaxOperator, - }, - }, - { - scope: ["keyword.conditional.ternary"], - style: { - foreground: theme.syntaxOperator, - }, - }, - { - scope: ["variable", "variable.parameter", "function.method.call", "function.call"], - style: { - foreground: theme.syntaxVariable, - }, - }, - { - scope: ["variable.member", "function", "constructor"], - style: { - foreground: theme.syntaxFunction, - }, - }, - { - scope: ["type", "module"], - style: { - foreground: theme.syntaxType, - }, - }, - { - scope: ["constant"], - style: { - foreground: theme.syntaxNumber, - }, - }, - { - scope: ["property"], - style: { - foreground: theme.syntaxVariable, - }, - }, - { - scope: ["class"], - style: { - foreground: theme.syntaxType, - }, - }, - { - scope: ["parameter"], - style: { - foreground: theme.syntaxVariable, - }, - }, - { - scope: ["punctuation", "punctuation.bracket"], - style: { - foreground: theme.syntaxPunctuation, - }, - }, - { - scope: ["variable.builtin", "type.builtin", "function.builtin", "module.builtin", "constant.builtin"], - style: { - foreground: theme.error, - }, - }, - { - scope: ["variable.super"], - style: { - foreground: theme.error, - }, - }, - { - scope: ["string.escape", "string.regexp"], - style: { - foreground: theme.syntaxKeyword, - }, - }, - { - scope: ["keyword.directive"], - style: { - foreground: theme.syntaxKeyword, - italic: true, - }, - }, - { - scope: ["punctuation.special"], - style: { - foreground: theme.syntaxOperator, - }, - }, - { - scope: ["keyword.modifier"], - style: { - foreground: theme.syntaxKeyword, - italic: true, - }, - }, - { - scope: ["keyword.exception"], - style: { - foreground: theme.syntaxKeyword, - italic: true, - }, - }, - // Markdown specific styles - { - scope: ["markup.heading"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.heading.1"], - style: { - foreground: theme.markdownHeading, - bold: true, - underline: true, - }, - }, - { - scope: ["markup.heading.2"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.heading.3"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.heading.4"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.heading.5"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.heading.6"], - style: { - foreground: theme.markdownHeading, - bold: true, - }, - }, - { - scope: ["markup.bold", "markup.strong"], - style: { - foreground: theme.markdownStrong, - bold: true, - }, - }, - { - scope: ["markup.italic"], - style: { - foreground: theme.markdownEmph, - italic: true, - }, - }, - { - scope: ["markup.list"], - style: { - foreground: theme.markdownListItem, - }, - }, - { - scope: ["markup.quote"], - style: { - foreground: theme.markdownBlockQuote, - italic: true, - }, - }, - { - scope: ["markup.raw", "markup.raw.block"], - style: { - foreground: theme.markdownCode, - }, - }, - { - scope: ["markup.raw.inline"], - style: { - foreground: theme.markdownCode, - background: theme.background, - }, - }, - { - scope: ["markup.link"], - style: { - foreground: theme.markdownLink, - underline: true, - }, - }, - { - scope: ["markup.link.label"], - style: { - foreground: theme.markdownLinkText, - underline: true, - }, - }, - { - scope: ["markup.link.url"], - style: { - foreground: theme.markdownLink, - underline: true, - }, - }, - { - scope: ["label"], - style: { - foreground: theme.markdownLinkText, - }, - }, - { - scope: ["spell", "nospell"], - style: { - foreground: theme.text, - }, - }, - // Additional common highlight groups - { - scope: ["string.special", "string.special.url"], - style: { - foreground: theme.markdownLink, - underline: true, - }, - }, - { - scope: ["character"], - style: { - foreground: theme.syntaxString, - }, - }, - { - scope: ["float"], - style: { - foreground: theme.syntaxNumber, - }, - }, - { - scope: ["comment.error"], - style: { - foreground: theme.error, - italic: true, - bold: true, - }, - }, - { - scope: ["comment.warning"], - style: { - foreground: theme.warning, - italic: true, - bold: true, - }, - }, - { - scope: ["comment.todo", "comment.note"], - style: { - foreground: theme.info, - italic: true, - bold: true, - }, - }, - { - scope: ["namespace"], - style: { - foreground: theme.syntaxType, - }, - }, - { - scope: ["field"], - style: { - foreground: theme.syntaxVariable, - }, - }, - { - scope: ["type.definition"], - style: { - foreground: theme.syntaxType, - bold: true, - }, - }, - { - scope: ["keyword.export"], - style: { - foreground: theme.syntaxKeyword, - }, - }, - { - scope: ["attribute", "annotation"], - style: { - foreground: theme.warning, - }, - }, - { - scope: ["tag"], - style: { - foreground: theme.error, - }, - }, - { - scope: ["tag.attribute"], - style: { - foreground: theme.syntaxKeyword, - }, - }, - { - scope: ["tag.delimiter"], - style: { - foreground: theme.syntaxOperator, - }, - }, - { - scope: ["markup.strikethrough"], - style: { - foreground: theme.textMuted, - }, - }, - { - scope: ["markup.underline"], - style: { - foreground: theme.text, - underline: true, - }, - }, - { - scope: ["markup.list.checked"], - style: { - foreground: theme.success, - }, - }, - { - scope: ["markup.list.unchecked"], - style: { - foreground: theme.textMuted, - }, - }, - { - scope: ["diff.plus"], - style: { - foreground: theme.diffAdded, - background: theme.diffAddedBg, - }, - }, - { - scope: ["diff.minus"], - style: { - foreground: theme.diffRemoved, - background: theme.diffRemovedBg, - }, - }, - { - scope: ["diff.delta"], - style: { - foreground: theme.diffContext, - background: theme.diffContextBg, - }, - }, - { - scope: ["error"], - style: { - foreground: theme.error, - bold: true, - }, - }, - { - scope: ["warning"], - style: { - foreground: theme.warning, - bold: true, - }, - }, - { - scope: ["info"], - style: { - foreground: theme.info, - }, - }, - { - scope: ["debug"], - style: { - foreground: theme.textMuted, - }, - }, - ] -} diff --git a/packages/tui/src/theme/v1.ts b/packages/tui/src/theme/v1.ts new file mode 100644 index 0000000000..f921038373 --- /dev/null +++ b/packages/tui/src/theme/v1.ts @@ -0,0 +1,661 @@ +import { RGBA, SyntaxStyle } from "@opentui/core" +import aura from "./assets/aura.json" with { type: "json" } +import ayu from "./assets/ayu.json" with { type: "json" } +import carbonfox from "./assets/carbonfox.json" with { type: "json" } +import catppuccinFrappe from "./assets/catppuccin-frappe.json" with { type: "json" } +import catppuccinMacchiato from "./assets/catppuccin-macchiato.json" with { type: "json" } +import catppuccin from "./assets/catppuccin.json" with { type: "json" } +import cobalt2 from "./assets/cobalt2.json" with { type: "json" } +import cursor from "./assets/cursor.json" with { type: "json" } +import dracula from "./assets/dracula.json" with { type: "json" } +import everforest from "./assets/everforest.json" with { type: "json" } +import flexoki from "./assets/flexoki.json" with { type: "json" } +import github from "./assets/github.json" with { type: "json" } +import gruvbox from "./assets/gruvbox.json" with { type: "json" } +import kanagawa from "./assets/kanagawa.json" with { type: "json" } +import lucentOrng from "./assets/lucent-orng.json" with { type: "json" } +import material from "./assets/material.json" with { type: "json" } +import matrix from "./assets/matrix.json" with { type: "json" } +import mercury from "./assets/mercury.json" with { type: "json" } +import monokai from "./assets/monokai.json" with { type: "json" } +import nightowl from "./assets/nightowl.json" with { type: "json" } +import nord from "./assets/nord.json" with { type: "json" } +import onedark from "./assets/one-dark.json" with { type: "json" } +import opencode from "./assets/opencode.json" with { type: "json" } +import orng from "./assets/orng.json" with { type: "json" } +import osakaJade from "./assets/osaka-jade.json" with { type: "json" } +import palenight from "./assets/palenight.json" with { type: "json" } +import rosepine from "./assets/rosepine.json" with { type: "json" } +import solarized from "./assets/solarized.json" with { type: "json" } +import synthwave84 from "./assets/synthwave84.json" with { type: "json" } +import tokyonight from "./assets/tokyonight.json" with { type: "json" } +import vercel from "./assets/vercel.json" with { type: "json" } +import vesper from "./assets/vesper.json" with { type: "json" } +import zenburn from "./assets/zenburn.json" with { type: "json" } + +export type Theme = { + readonly primary: RGBA + readonly secondary: RGBA + readonly accent: RGBA + readonly error: RGBA + readonly warning: RGBA + readonly success: RGBA + readonly info: RGBA + readonly text: RGBA + readonly textMuted: RGBA + readonly selectedListItemText: RGBA + readonly background: RGBA + readonly backgroundPanel: RGBA + readonly backgroundElement: RGBA + readonly backgroundMenu: RGBA + readonly border: RGBA + readonly borderActive: RGBA + readonly borderSubtle: RGBA + readonly diffAdded: RGBA + readonly diffRemoved: RGBA + readonly diffContext: RGBA + readonly diffHunkHeader: RGBA + readonly diffHighlightAdded: RGBA + readonly diffHighlightRemoved: RGBA + readonly diffAddedBg: RGBA + readonly diffRemovedBg: RGBA + readonly diffContextBg: RGBA + readonly diffLineNumber: RGBA + readonly diffAddedLineNumberBg: RGBA + readonly diffRemovedLineNumberBg: RGBA + readonly markdownText: RGBA + readonly markdownHeading: RGBA + readonly markdownLink: RGBA + readonly markdownLinkText: RGBA + readonly markdownCode: RGBA + readonly markdownBlockQuote: RGBA + readonly markdownEmph: RGBA + readonly markdownStrong: RGBA + readonly markdownHorizontalRule: RGBA + readonly markdownListItem: RGBA + readonly markdownListEnumeration: RGBA + readonly markdownImage: RGBA + readonly markdownImageText: RGBA + readonly markdownCodeBlock: RGBA + readonly syntaxComment: RGBA + readonly syntaxKeyword: RGBA + readonly syntaxFunction: RGBA + readonly syntaxVariable: RGBA + readonly syntaxString: RGBA + readonly syntaxNumber: RGBA + readonly syntaxType: RGBA + readonly syntaxOperator: RGBA + readonly syntaxPunctuation: RGBA + readonly thinkingOpacity: number + _hasSelectedListItemText: boolean +} + +export type ThemeColor = Exclude +export type HexColor = `#${string}` +export type RefName = string +export type Variant = { + dark: HexColor | RefName + light: HexColor | RefName +} +export type ColorValue = HexColor | RefName | Variant | RGBA +export type ThemeJson = { + $schema?: string + defs?: Record + theme: Omit, "selectedListItemText" | "backgroundMenu"> & { + selectedListItemText?: ColorValue + backgroundMenu?: ColorValue + thinkingOpacity?: number + } +} + +export const DEFAULT_THEMES: Record = { + aura, + ayu, + catppuccin, + ["catppuccin-frappe"]: catppuccinFrappe, + ["catppuccin-macchiato"]: catppuccinMacchiato, + cobalt2, + cursor, + dracula, + everforest, + flexoki, + github, + gruvbox, + kanagawa, + material, + matrix, + mercury, + monokai, + nightowl, + nord, + ["one-dark"]: onedark, + ["osaka-jade"]: osakaJade, + opencode, + orng, + ["lucent-orng"]: lucentOrng, + palenight, + rosepine, + solarized, + synthwave84, + tokyonight, + vesper, + vercel, + zenburn, + carbonfox, +} + +export function selectedForeground(theme: Theme, bg?: RGBA): RGBA { + if (theme._hasSelectedListItemText) return theme.selectedListItemText + + if (theme.background.a === 0) { + const targetColor = bg ?? theme.primary + const { r, g, b } = targetColor + const luminance = 0.299 * r + 0.587 * g + 0.114 * b + return luminance > 0.5 ? RGBA.fromInts(0, 0, 0) : RGBA.fromInts(255, 255, 255) + } + + return theme.background +} + +export function generateSyntax(theme: Theme) { + return SyntaxStyle.fromTheme(getSyntaxRules(theme)) +} + +function getSyntaxRules(theme: Theme) { + return [ + { + scope: ["default"], + style: { + foreground: theme.text, + }, + }, + { + scope: ["prompt"], + style: { + foreground: theme.accent, + }, + }, + { + scope: ["extmark.file"], + style: { + foreground: theme.warning, + bold: true, + }, + }, + { + scope: ["extmark.agent"], + style: { + foreground: theme.secondary, + bold: true, + }, + }, + { + scope: ["extmark.paste"], + style: { + foreground: selectedForeground(theme, theme.warning), + background: theme.warning, + bold: true, + }, + }, + { + scope: ["comment"], + style: { + foreground: theme.syntaxComment, + italic: true, + }, + }, + { + scope: ["comment.documentation"], + style: { + foreground: theme.syntaxComment, + italic: true, + }, + }, + { + scope: ["string", "symbol"], + style: { + foreground: theme.syntaxString, + }, + }, + { + scope: ["number", "boolean"], + style: { + foreground: theme.syntaxNumber, + }, + }, + { + scope: ["character.special"], + style: { + foreground: theme.syntaxString, + }, + }, + { + scope: ["keyword.return", "keyword.conditional", "keyword.repeat", "keyword.coroutine"], + style: { + foreground: theme.syntaxKeyword, + italic: true, + }, + }, + { + scope: ["keyword.type"], + style: { + foreground: theme.syntaxType, + bold: true, + italic: true, + }, + }, + { + scope: ["keyword.function", "function.method"], + style: { + foreground: theme.syntaxFunction, + }, + }, + { + scope: ["keyword"], + style: { + foreground: theme.syntaxKeyword, + italic: true, + }, + }, + { + scope: ["keyword.import"], + style: { + foreground: theme.syntaxKeyword, + }, + }, + { + scope: ["operator", "keyword.operator", "punctuation.delimiter"], + style: { + foreground: theme.syntaxOperator, + }, + }, + { + scope: ["keyword.conditional.ternary"], + style: { + foreground: theme.syntaxOperator, + }, + }, + { + scope: ["variable", "variable.parameter", "function.method.call", "function.call"], + style: { + foreground: theme.syntaxVariable, + }, + }, + { + scope: ["variable.member", "function", "constructor"], + style: { + foreground: theme.syntaxFunction, + }, + }, + { + scope: ["type", "module"], + style: { + foreground: theme.syntaxType, + }, + }, + { + scope: ["constant"], + style: { + foreground: theme.syntaxNumber, + }, + }, + { + scope: ["property"], + style: { + foreground: theme.syntaxVariable, + }, + }, + { + scope: ["class"], + style: { + foreground: theme.syntaxType, + }, + }, + { + scope: ["parameter"], + style: { + foreground: theme.syntaxVariable, + }, + }, + { + scope: ["punctuation", "punctuation.bracket"], + style: { + foreground: theme.syntaxPunctuation, + }, + }, + { + scope: ["variable.builtin", "type.builtin", "function.builtin", "module.builtin", "constant.builtin"], + style: { + foreground: theme.error, + }, + }, + { + scope: ["variable.super"], + style: { + foreground: theme.error, + }, + }, + { + scope: ["string.escape", "string.regexp"], + style: { + foreground: theme.syntaxKeyword, + }, + }, + { + scope: ["keyword.directive"], + style: { + foreground: theme.syntaxKeyword, + italic: true, + }, + }, + { + scope: ["punctuation.special"], + style: { + foreground: theme.syntaxOperator, + }, + }, + { + scope: ["keyword.modifier"], + style: { + foreground: theme.syntaxKeyword, + italic: true, + }, + }, + { + scope: ["keyword.exception"], + style: { + foreground: theme.syntaxKeyword, + italic: true, + }, + }, + // Markdown specific styles + { + scope: ["markup.heading"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.heading.1"], + style: { + foreground: theme.markdownHeading, + bold: true, + underline: true, + }, + }, + { + scope: ["markup.heading.2"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.heading.3"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.heading.4"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.heading.5"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.heading.6"], + style: { + foreground: theme.markdownHeading, + bold: true, + }, + }, + { + scope: ["markup.bold", "markup.strong"], + style: { + foreground: theme.markdownStrong, + bold: true, + }, + }, + { + scope: ["markup.italic"], + style: { + foreground: theme.markdownEmph, + italic: true, + }, + }, + { + scope: ["markup.list"], + style: { + foreground: theme.markdownListItem, + }, + }, + { + scope: ["markup.quote"], + style: { + foreground: theme.markdownBlockQuote, + italic: true, + }, + }, + { + scope: ["markup.raw", "markup.raw.block"], + style: { + foreground: theme.markdownCode, + }, + }, + { + scope: ["markup.raw.inline"], + style: { + foreground: theme.markdownCode, + background: theme.background, + }, + }, + { + scope: ["markup.link"], + style: { + foreground: theme.markdownLink, + underline: true, + }, + }, + { + scope: ["markup.link.label"], + style: { + foreground: theme.markdownLinkText, + underline: true, + }, + }, + { + scope: ["markup.link.url"], + style: { + foreground: theme.markdownLink, + underline: true, + }, + }, + { + scope: ["label"], + style: { + foreground: theme.markdownLinkText, + }, + }, + { + scope: ["spell", "nospell"], + style: { + foreground: theme.text, + }, + }, + // Additional common highlight groups + { + scope: ["string.special", "string.special.url"], + style: { + foreground: theme.markdownLink, + underline: true, + }, + }, + { + scope: ["character"], + style: { + foreground: theme.syntaxString, + }, + }, + { + scope: ["float"], + style: { + foreground: theme.syntaxNumber, + }, + }, + { + scope: ["comment.error"], + style: { + foreground: theme.error, + italic: true, + bold: true, + }, + }, + { + scope: ["comment.warning"], + style: { + foreground: theme.warning, + italic: true, + bold: true, + }, + }, + { + scope: ["comment.todo", "comment.note"], + style: { + foreground: theme.info, + italic: true, + bold: true, + }, + }, + { + scope: ["namespace"], + style: { + foreground: theme.syntaxType, + }, + }, + { + scope: ["field"], + style: { + foreground: theme.syntaxVariable, + }, + }, + { + scope: ["type.definition"], + style: { + foreground: theme.syntaxType, + bold: true, + }, + }, + { + scope: ["keyword.export"], + style: { + foreground: theme.syntaxKeyword, + }, + }, + { + scope: ["attribute", "annotation"], + style: { + foreground: theme.warning, + }, + }, + { + scope: ["tag"], + style: { + foreground: theme.error, + }, + }, + { + scope: ["tag.attribute"], + style: { + foreground: theme.syntaxKeyword, + }, + }, + { + scope: ["tag.delimiter"], + style: { + foreground: theme.syntaxOperator, + }, + }, + { + scope: ["markup.strikethrough"], + style: { + foreground: theme.textMuted, + }, + }, + { + scope: ["markup.underline"], + style: { + foreground: theme.text, + underline: true, + }, + }, + { + scope: ["markup.list.checked"], + style: { + foreground: theme.success, + }, + }, + { + scope: ["markup.list.unchecked"], + style: { + foreground: theme.textMuted, + }, + }, + { + scope: ["diff.plus"], + style: { + foreground: theme.diffAdded, + background: theme.diffAddedBg, + }, + }, + { + scope: ["diff.minus"], + style: { + foreground: theme.diffRemoved, + background: theme.diffRemovedBg, + }, + }, + { + scope: ["diff.delta"], + style: { + foreground: theme.diffContext, + background: theme.diffContextBg, + }, + }, + { + scope: ["error"], + style: { + foreground: theme.error, + bold: true, + }, + }, + { + scope: ["warning"], + style: { + foreground: theme.warning, + bold: true, + }, + }, + { + scope: ["info"], + style: { + foreground: theme.info, + }, + }, + { + scope: ["debug"], + style: { + foreground: theme.textMuted, + }, + }, + ] +}