hermes-agent / apps /desktop /src /components /chat /code-editor-theme.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
a1b6014 verified
Raw History Blame Contribute Delete
3.74 kB
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
import type { Extension } from '@codemirror/state'
import { EditorView } from '@codemirror/view'
import { tags as t } from '@lezer/highlight'
// GitHub "default" palettes, mirroring the read view's Shiki themes
// (`github-light-default` / `github-dark-default`) so the spot editor matches
// the preview it replaces. These are token *colors*; CodeMirror tokenizes with
// Lezer rather than Shiki's TextMate grammars, so it's a palette match rather
// than a byte-identical one — close enough that switching in/out of edit mode
// doesn't recolor the file.
interface GithubPalette {
comment: string
constant: string
entity: string
fg: string
keyword: string
number: string
string: string
tag: string
type: string
}
const DARK: GithubPalette = {
comment: '#8b949e',
constant: '#79c0ff',
entity: '#d2a8ff',
fg: '#e6edf3',
keyword: '#ff7b72',
number: '#79c0ff',
string: '#a5d6ff',
tag: '#7ee787',
type: '#ffa657'
}
const LIGHT: GithubPalette = {
comment: '#6e7781',
constant: '#0550ae',
entity: '#8250df',
fg: '#1f2328',
keyword: '#cf222e',
number: '#0550ae',
string: '#0a3069',
tag: '#116329',
type: '#953800'
}
function makeHighlightStyle(p: GithubPalette): HighlightStyle {
return HighlightStyle.define([
{ color: p.keyword, tag: [t.keyword, t.modifier, t.controlKeyword, t.operatorKeyword, t.moduleKeyword] },
{ color: p.string, tag: [t.string, t.special(t.string), t.attributeValue] },
{ color: p.tag, tag: [t.regexp, t.escape] },
{ color: p.comment, fontStyle: 'italic', tag: [t.comment, t.lineComment, t.blockComment, t.docComment] },
{
color: p.entity,
tag: [
t.function(t.variableName),
t.function(t.propertyName),
t.definition(t.function(t.variableName)),
t.labelName
]
},
{ color: p.number, tag: [t.number, t.bool, t.atom] },
{ color: p.constant, tag: [t.constant(t.variableName), t.standard(t.variableName)] },
{ color: p.type, tag: [t.typeName, t.className, t.namespace] },
{ color: p.tag, tag: [t.tagName] },
{ color: p.constant, tag: [t.attributeName, t.propertyName] },
{ color: p.fg, tag: [t.variableName] },
{ color: p.fg, tag: [t.operator, t.punctuation, t.separator, t.bracket, t.angleBracket, t.derefOperator] },
{ color: p.comment, tag: [t.meta, t.processingInstruction] },
{ color: p.constant, tag: [t.link, t.url], textDecoration: 'underline' },
{ color: p.constant, fontWeight: 'bold', tag: [t.heading] },
{ fontWeight: 'bold', tag: [t.strong] },
{ fontStyle: 'italic', tag: [t.emphasis] },
{ color: p.keyword, tag: [t.deleted, t.invalid] }
])
}
const DARK_STYLE = makeHighlightStyle(DARK)
const LIGHT_STYLE = makeHighlightStyle(LIGHT)
// Editor chrome (caret, selection, active line, gutters) on a transparent
// background so the pane surface shows through, paired with the matching
// GitHub highlight style.
export function githubEditorTheme(dark: boolean): Extension {
const p = dark ? DARK : LIGHT
return [
EditorView.theme(
{
'&': { backgroundColor: 'transparent', color: p.fg },
'&.cm-focused .cm-selectionBackground, .cm-content ::selection, .cm-selectionBackground': {
backgroundColor: dark ? 'rgba(56,139,253,0.25)' : 'rgba(84,174,255,0.28)'
},
// Match the read view's gutter: dim, right-aligned line numbers.
'.cm-content': { caretColor: p.fg },
'.cm-cursor, .cm-dropCursor': { borderLeftColor: p.fg },
'.cm-gutters': { backgroundColor: 'transparent', border: 'none' }
},
{ dark }
),
syntaxHighlighting(dark ? DARK_STYLE : LIGHT_STYLE)
]
}