Buckets:
| import { SyntaxStyle, RGBA, type TerminalColors } 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 | |
| } | |
| type ThemeColor = Exclude<keyof Theme, "thinkingOpacity" | "_hasSelectedListItemText"> | |
| export type SyntaxStyleOverrides = Record<string, { italic?: boolean }> | |
| 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<string, HexColor | RefName> | |
| theme: Omit<Record<ThemeColor, ColorValue>, "selectedListItemText" | "backgroundMenu"> & { | |
| selectedListItemText?: ColorValue | |
| backgroundMenu?: ColorValue | |
| thinkingOpacity?: number | |
| } | |
| } | |
| export const DEFAULT_THEMES: Record<string, ThemeJson> = { | |
| 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, | |
| } | |
| const pluginThemes: Record<string, ThemeJson> = {} | |
| let customThemes: Record<string, ThemeJson> = {} | |
| let systemTheme: ThemeJson | undefined | |
| const listeners = new Set<(themes: Record<string, ThemeJson>) => void>() | |
| function listThemes() { | |
| // Priority: defaults < plugin installs < custom files < generated system. | |
| const themes = { | |
| ...DEFAULT_THEMES, | |
| ...pluginThemes, | |
| ...customThemes, | |
| } | |
| if (!systemTheme) return themes | |
| return { | |
| ...themes, | |
| system: systemTheme, | |
| } | |
| } | |
| function syncThemes() { | |
| const themes = listThemes() | |
| for (const listener of listeners) listener(themes) | |
| } | |
| export function allThemes() { | |
| return listThemes() | |
| } | |
| export function isTheme(theme: unknown): theme is ThemeJson { | |
| if (typeof theme !== "object" || theme === null || Array.isArray(theme)) return false | |
| const value = Reflect.get(theme, "theme") | |
| return typeof value === "object" && value !== null && !Array.isArray(value) | |
| } | |
| export function subscribeThemes(listener: (themes: Record<string, ThemeJson>) => void) { | |
| listeners.add(listener) | |
| return () => listeners.delete(listener) | |
| } | |
| export function setCustomThemes(themes: Record<string, ThemeJson>) { | |
| customThemes = themes | |
| syncThemes() | |
| } | |
| export function setSystemTheme(theme: ThemeJson | undefined) { | |
| systemTheme = theme | |
| syncThemes() | |
| } | |
| export function hasTheme(name: string) { | |
| if (!name) return false | |
| return allThemes()[name] !== undefined | |
| } | |
| export function addTheme(name: string, theme: unknown) { | |
| if (!name) return false | |
| if (!isTheme(theme)) return false | |
| if (hasTheme(name)) return false | |
| pluginThemes[name] = theme | |
| syncThemes() | |
| return true | |
| } | |
| export function upsertTheme(name: string, theme: unknown) { | |
| if (!name) return false | |
| if (!isTheme(theme)) return false | |
| if (customThemes[name] !== undefined) { | |
| customThemes[name] = theme | |
| } else { | |
| pluginThemes[name] = theme | |
| } | |
| syncThemes() | |
| return true | |
| } | |
| export function resolveTheme(theme: ThemeJson, mode: "dark" | "light") { | |
| const defs = theme.defs ?? {} | |
| function resolveColor(c: ColorValue, chain: string[] = []): RGBA { | |
| if (c instanceof RGBA) return c | |
| if (typeof c === "string") { | |
| if (c === "transparent" || c === "none") return RGBA.fromInts(0, 0, 0, 0) | |
| if (c.startsWith("#")) return RGBA.fromHex(c) | |
| if (chain.includes(c)) { | |
| throw new Error(`Circular color reference: ${[...chain, c].join(" -> ")}`) | |
| } | |
| const next = defs[c] ?? theme.theme[c as ThemeColor] | |
| if (next === undefined) { | |
| throw new Error(`Color reference "${c}" not found in defs or theme`) | |
| } | |
| return resolveColor(next, [...chain, c]) | |
| } | |
| if (typeof c === "number") { | |
| return ansiToRgba(c) | |
| } | |
| return resolveColor(c[mode], chain) | |
| } | |
| const resolved = Object.fromEntries( | |
| Object.entries(theme.theme) | |
| .filter(([key]) => key !== "selectedListItemText" && key !== "backgroundMenu" && key !== "thinkingOpacity") | |
| .map(([key, value]) => { | |
| return [key, resolveColor(value as ColorValue)] | |
| }), | |
| ) as Partial<Record<ThemeColor, RGBA>> | |
| // Handle selectedListItemText separately since it's optional | |
| const hasSelectedListItemText = theme.theme.selectedListItemText !== undefined | |
| if (hasSelectedListItemText) { | |
| resolved.selectedListItemText = resolveColor(theme.theme.selectedListItemText!) | |
| } else { | |
| // Backward compatibility: if selectedListItemText is not defined, use background color | |
| // This preserves the current behavior for all existing themes | |
| resolved.selectedListItemText = resolved.background | |
| } | |
| // Handle backgroundMenu - optional with fallback to backgroundElement | |
| if (theme.theme.backgroundMenu !== undefined) { | |
| resolved.backgroundMenu = resolveColor(theme.theme.backgroundMenu) | |
| } else { | |
| resolved.backgroundMenu = resolved.backgroundElement | |
| } | |
| // Handle thinkingOpacity - optional with default of 0.6 | |
| const thinkingOpacity = theme.theme.thinkingOpacity ?? 0.6 | |
| return { | |
| ...resolved, | |
| _hasSelectedListItemText: hasSelectedListItemText, | |
| thinkingOpacity, | |
| } as Theme | |
| } | |
| function ansiToRgba(code: number): RGBA { | |
| // Standard ANSI colors (0-15) | |
| if (code < 16) { | |
| const ansiColors = [ | |
| "#000000", // Black | |
| "#800000", // Red | |
| "#008000", // Green | |
| "#808000", // Yellow | |
| "#000080", // Blue | |
| "#800080", // Magenta | |
| "#008080", // Cyan | |
| "#c0c0c0", // White | |
| "#808080", // Bright Black | |
| "#ff0000", // Bright Red | |
| "#00ff00", // Bright Green | |
| "#ffff00", // Bright Yellow | |
| "#0000ff", // Bright Blue | |
| "#ff00ff", // Bright Magenta | |
| "#00ffff", // Bright Cyan | |
| "#ffffff", // Bright White | |
| ] | |
| return RGBA.fromHex(ansiColors[code] ?? "#000000") | |
| } | |
| // 6x6x6 Color Cube (16-231) | |
| if (code < 232) { | |
| const index = code - 16 | |
| const b = index % 6 | |
| const g = Math.floor(index / 6) % 6 | |
| const r = Math.floor(index / 36) | |
| const val = (x: number) => (x === 0 ? 0 : x * 40 + 55) | |
| return RGBA.fromInts(val(r), val(g), val(b)) | |
| } | |
| // Grayscale Ramp (232-255) | |
| if (code < 256) { | |
| const gray = (code - 232) * 10 + 8 | |
| return RGBA.fromInts(gray, gray, gray) | |
| } | |
| // Fallback for invalid codes | |
| return RGBA.fromInts(0, 0, 0) | |
| } | |
| export function tint(base: RGBA, overlay: RGBA, alpha: number): RGBA { | |
| const r = base.r + (overlay.r - base.r) * alpha | |
| const g = base.g + (overlay.g - base.g) * alpha | |
| const b = base.b + (overlay.b - base.b) * alpha | |
| return RGBA.fromInts(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)) | |
| } | |
| export function terminalMode(colors: TerminalColors): "dark" | "light" | undefined { | |
| const bg = colors.defaultBackground | |
| if (!bg) return | |
| const { r, g, b } = RGBA.fromHex(bg) | |
| return 0.299 * r + 0.587 * g + 0.114 * b > 0.5 ? "light" : "dark" | |
| } | |
| export function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJson { | |
| const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0]!) | |
| const fg = RGBA.fromHex(colors.defaultForeground ?? colors.palette[7]!) | |
| const transparent = RGBA.fromValues(bg.r, bg.g, bg.b, 0) | |
| const isDark = mode == "dark" | |
| const col = (i: number) => { | |
| const value = colors.palette[i] | |
| if (value) return RGBA.fromHex(value) | |
| return ansiToRgba(i) | |
| } | |
| // Generate gray scale based on terminal background | |
| const grays = generateGrayScale(bg, isDark) | |
| const textMuted = generateMutedTextColor(bg, isDark) | |
| // ANSI color references | |
| const ansiColors = { | |
| black: col(0), | |
| red: col(1), | |
| green: col(2), | |
| yellow: col(3), | |
| blue: col(4), | |
| magenta: col(5), | |
| cyan: col(6), | |
| white: col(7), | |
| redBright: col(9), | |
| greenBright: col(10), | |
| } | |
| const diffAlpha = isDark ? 0.22 : 0.14 | |
| const diffAddedBg = tint(bg, ansiColors.green, diffAlpha) | |
| const diffRemovedBg = tint(bg, ansiColors.red, diffAlpha) | |
| const diffContextBg = grays[2] | |
| const diffAddedLineNumberBg = tint(diffContextBg, ansiColors.green, diffAlpha) | |
| const diffRemovedLineNumberBg = tint(diffContextBg, ansiColors.red, diffAlpha) | |
| const diffLineNumber = textMuted | |
| return { | |
| theme: { | |
| // Primary colors using ANSI | |
| primary: ansiColors.cyan, | |
| secondary: ansiColors.magenta, | |
| accent: ansiColors.cyan, | |
| // Status colors using ANSI | |
| error: ansiColors.red, | |
| warning: ansiColors.yellow, | |
| success: ansiColors.green, | |
| info: ansiColors.cyan, | |
| // Text colors | |
| text: fg, | |
| textMuted, | |
| selectedListItemText: bg, | |
| // Background colors - use transparent to respect terminal transparency | |
| background: transparent, | |
| backgroundPanel: grays[2], | |
| backgroundElement: grays[3], | |
| backgroundMenu: grays[3], | |
| // Border colors | |
| borderSubtle: grays[6], | |
| border: grays[7], | |
| borderActive: grays[8], | |
| // Diff colors | |
| diffAdded: ansiColors.green, | |
| diffRemoved: ansiColors.red, | |
| diffContext: grays[7], | |
| diffHunkHeader: grays[7], | |
| diffHighlightAdded: ansiColors.greenBright, | |
| diffHighlightRemoved: ansiColors.redBright, | |
| diffAddedBg, | |
| diffRemovedBg, | |
| diffContextBg, | |
| diffLineNumber, | |
| diffAddedLineNumberBg, | |
| diffRemovedLineNumberBg, | |
| // Markdown colors | |
| markdownText: fg, | |
| markdownHeading: fg, | |
| markdownLink: ansiColors.blue, | |
| markdownLinkText: ansiColors.cyan, | |
| markdownCode: ansiColors.green, | |
| markdownBlockQuote: ansiColors.yellow, | |
| markdownEmph: ansiColors.yellow, | |
| markdownStrong: fg, | |
| markdownHorizontalRule: grays[7], | |
| markdownListItem: ansiColors.blue, | |
| markdownListEnumeration: ansiColors.cyan, | |
| markdownImage: ansiColors.blue, | |
| markdownImageText: ansiColors.cyan, | |
| markdownCodeBlock: fg, | |
| // Syntax colors | |
| syntaxComment: textMuted, | |
| syntaxKeyword: ansiColors.magenta, | |
| syntaxFunction: ansiColors.blue, | |
| syntaxVariable: fg, | |
| syntaxString: ansiColors.green, | |
| syntaxNumber: ansiColors.yellow, | |
| syntaxType: ansiColors.cyan, | |
| syntaxOperator: ansiColors.cyan, | |
| syntaxPunctuation: fg, | |
| }, | |
| } | |
| } | |
| function generateGrayScale(bg: RGBA, isDark: boolean): Record<number, RGBA> { | |
| const grays: Record<number, RGBA> = {} | |
| // RGBA stores floats in range 0-1, convert to 0-255 | |
| const bgR = bg.r * 255 | |
| const bgG = bg.g * 255 | |
| const bgB = bg.b * 255 | |
| const luminance = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB | |
| for (let i = 1; i <= 12; i++) { | |
| const factor = i / 12.0 | |
| let grayValue: number | |
| let newR: number | |
| let newG: number | |
| let newB: number | |
| if (isDark) { | |
| if (luminance < 10) { | |
| grayValue = Math.floor(factor * 0.4 * 255) | |
| newR = grayValue | |
| newG = grayValue | |
| newB = grayValue | |
| } else { | |
| const newLum = luminance + (255 - luminance) * factor * 0.4 | |
| const ratio = newLum / luminance | |
| newR = Math.min(bgR * ratio, 255) | |
| newG = Math.min(bgG * ratio, 255) | |
| newB = Math.min(bgB * ratio, 255) | |
| } | |
| } else { | |
| if (luminance > 245) { | |
| grayValue = Math.floor(255 - factor * 0.4 * 255) | |
| newR = grayValue | |
| newG = grayValue | |
| newB = grayValue | |
| } else { | |
| const newLum = luminance * (1 - factor * 0.4) | |
| const ratio = newLum / luminance | |
| newR = Math.max(bgR * ratio, 0) | |
| newG = Math.max(bgG * ratio, 0) | |
| newB = Math.max(bgB * ratio, 0) | |
| } | |
| } | |
| grays[i] = RGBA.fromInts(Math.floor(newR), Math.floor(newG), Math.floor(newB)) | |
| } | |
| return grays | |
| } | |
| function generateMutedTextColor(bg: RGBA, isDark: boolean): RGBA { | |
| // RGBA stores floats in range 0-1, convert to 0-255 | |
| const bgR = bg.r * 255 | |
| const bgG = bg.g * 255 | |
| const bgB = bg.b * 255 | |
| const bgLum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB | |
| let grayValue: number | |
| if (isDark) { | |
| if (bgLum < 10) { | |
| // Very dark/black background | |
| grayValue = 180 // #b4b4b4 | |
| } else { | |
| // Scale up for lighter dark backgrounds | |
| grayValue = Math.min(Math.floor(160 + bgLum * 0.3), 200) | |
| } | |
| } else { | |
| if (bgLum > 245) { | |
| // Very light/white background | |
| grayValue = 75 // #4b4b4b | |
| } else { | |
| // Scale down for darker light backgrounds | |
| grayValue = Math.max(Math.floor(100 - (255 - bgLum) * 0.2), 60) | |
| } | |
| } | |
| return RGBA.fromInts(grayValue, grayValue, grayValue) | |
| } | |
| export function generateSyntax(theme: Theme) { | |
| return SyntaxStyle.fromTheme(getSyntaxRules(theme)) | |
| } | |
| export function generateSubtleSyntax(theme: Theme, overrides?: SyntaxStyleOverrides) { | |
| const rules = getSyntaxRules(theme) | |
| return SyntaxStyle.fromTheme( | |
| rules.map((rule) => { | |
| const override = rule.scope.reduce((acc, scope) => ({ ...acc, ...overrides?.[scope] }), {}) | |
| if (rule.style.foreground) { | |
| const fg = rule.style.foreground | |
| return { | |
| ...rule, | |
| style: { | |
| ...rule.style, | |
| ...override, | |
| foreground: RGBA.fromInts( | |
| Math.round(fg.r * 255), | |
| Math.round(fg.g * 255), | |
| Math.round(fg.b * 255), | |
| Math.round(theme.thinkingOpacity * 255), | |
| ), | |
| }, | |
| } | |
| } | |
| return rule | |
| }), | |
| ) | |
| } | |
| 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, | |
| }, | |
| }, | |
| { | |
| scope: ["conceal"], | |
| style: { | |
| foreground: theme.textMuted, | |
| }, | |
| }, | |
| // 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, | |
| }, | |
| }, | |
| ] | |
| } | |
Xet Storage Details
- Size:
- 27.8 kB
- Xet hash:
- d0588b7f64d04048ebf799efc9c3abcf5e8d8b4dff8bc99a38d27ece03043362
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.