211 lines
5.9 KiB
TypeScript
211 lines
5.9 KiB
TypeScript
import { EditorView } from "@codemirror/view";
|
|
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
import { tags as t } from "@lezer/highlight";
|
|
|
|
interface ThemeColors {
|
|
background: string;
|
|
surface: string;
|
|
text: string;
|
|
selection: string;
|
|
activeLine: string;
|
|
cursor: string;
|
|
border: string;
|
|
keyword: string;
|
|
string: string;
|
|
number: string;
|
|
comment: string;
|
|
variable: string;
|
|
function: string;
|
|
heading: string;
|
|
}
|
|
|
|
const palette: Record<"light" | "dark", ThemeColors> = {
|
|
light: {
|
|
background: "#ffffff",
|
|
surface: "#f6f7f9",
|
|
text: "#14161a",
|
|
selection: "#dbe6fe",
|
|
activeLine: "#f6f7f9",
|
|
cursor: "#3b6cf6",
|
|
border: "#dfe2e7",
|
|
keyword: "#7c3aed",
|
|
string: "#0f766e",
|
|
number: "#b45309",
|
|
comment: "#6b7280",
|
|
variable: "#14161a",
|
|
function: "#2563eb",
|
|
heading: "#1d4ed8",
|
|
},
|
|
dark: {
|
|
background: "#16181d",
|
|
surface: "#1d2026",
|
|
text: "#eef0f4",
|
|
selection: "#2f3a52",
|
|
activeLine: "#1d2026",
|
|
cursor: "#6b93ff",
|
|
border: "#2f343d",
|
|
keyword: "#c4a7f7",
|
|
string: "#8ddba4",
|
|
number: "#f0b37e",
|
|
comment: "#7b8496",
|
|
variable: "#eef0f4",
|
|
function: "#7aa2ff",
|
|
heading: "#8fb3ff",
|
|
},
|
|
};
|
|
|
|
export function editorTheme(isDark: boolean) {
|
|
const colors = palette[isDark ? "dark" : "light"];
|
|
|
|
const theme = EditorView.theme(
|
|
{
|
|
"&": {
|
|
color: colors.text,
|
|
backgroundColor: colors.background,
|
|
height: "100%",
|
|
fontSize: "13px",
|
|
},
|
|
".cm-content": {
|
|
caretColor: colors.cursor,
|
|
padding: "12px 0",
|
|
},
|
|
".cm-cursor, .cm-dropCursor": { borderLeftColor: colors.cursor },
|
|
"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":
|
|
{ backgroundColor: colors.selection },
|
|
".cm-activeLine": { backgroundColor: colors.activeLine },
|
|
".cm-gutters": {
|
|
backgroundColor: colors.background,
|
|
color: colors.comment,
|
|
border: "none",
|
|
},
|
|
".cm-activeLineGutter": { backgroundColor: colors.activeLine },
|
|
"&.cm-focused .cm-matchingBracket": {
|
|
backgroundColor: colors.selection,
|
|
outline: `1px solid ${colors.border}`,
|
|
},
|
|
|
|
".cm-tooltip": {
|
|
backgroundColor: colors.surface,
|
|
color: colors.text,
|
|
border: `1px solid ${colors.border}`,
|
|
borderRadius: "6px",
|
|
maxWidth: "500px",
|
|
},
|
|
".cm-tooltip-hover": { maxHeight: "300px", overflow: "auto" },
|
|
".cm-tooltip .cm-tooltip-arrow:before": {
|
|
borderTopColor: colors.border,
|
|
borderBottomColor: colors.border,
|
|
},
|
|
".cm-tooltip .cm-tooltip-arrow:after": {
|
|
borderTopColor: colors.surface,
|
|
borderBottomColor: colors.surface,
|
|
},
|
|
|
|
".cm-tooltip.cm-tooltip-autocomplete": {
|
|
backgroundColor: colors.surface,
|
|
border: `1px solid ${colors.border}`,
|
|
padding: "4px",
|
|
},
|
|
".cm-tooltip.cm-tooltip-autocomplete > ul": {
|
|
fontFamily: "inherit",
|
|
maxHeight: "16em",
|
|
},
|
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li": {
|
|
color: colors.text,
|
|
padding: "3px 8px",
|
|
borderRadius: "4px",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: "6px",
|
|
},
|
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
|
|
backgroundColor: colors.cursor,
|
|
color: "#ffffff",
|
|
},
|
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] .cm-completionDetail":
|
|
{ color: "#ffffff" },
|
|
".cm-completionLabel": { color: "inherit" },
|
|
".cm-completionMatchedText": {
|
|
textDecoration: "none",
|
|
fontWeight: "600",
|
|
color: "inherit",
|
|
},
|
|
".cm-completionDetail": {
|
|
color: colors.comment,
|
|
fontStyle: "normal",
|
|
marginLeft: "auto",
|
|
fontSize: "0.85em",
|
|
},
|
|
".cm-completionIcon": {
|
|
color: colors.comment,
|
|
opacity: "1",
|
|
width: "1.1em",
|
|
},
|
|
".cm-completionInfo": {
|
|
backgroundColor: colors.surface,
|
|
color: colors.text,
|
|
border: `1px solid ${colors.border}`,
|
|
borderRadius: "6px",
|
|
padding: "6px 8px",
|
|
},
|
|
|
|
".cm-panels": { backgroundColor: colors.surface, color: colors.text },
|
|
".cm-searchMatch": { backgroundColor: "#72a1ff59" },
|
|
".cm-selectionMatch": { backgroundColor: "#aafe661a" },
|
|
},
|
|
{ dark: isDark },
|
|
);
|
|
|
|
const highlightStyle = HighlightStyle.define([
|
|
{ tag: t.keyword, color: colors.keyword },
|
|
{
|
|
tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
|
|
color: colors.variable,
|
|
},
|
|
{ tag: [t.function(t.variableName), t.labelName], color: colors.function },
|
|
{
|
|
tag: [t.color, t.constant(t.name), t.standard(t.name)],
|
|
color: colors.function,
|
|
},
|
|
{ tag: [t.definition(t.name), t.separator], color: colors.variable },
|
|
{
|
|
tag: [
|
|
t.typeName,
|
|
t.className,
|
|
t.number,
|
|
t.changed,
|
|
t.annotation,
|
|
t.modifier,
|
|
t.self,
|
|
t.namespace,
|
|
],
|
|
color: colors.number,
|
|
},
|
|
{
|
|
tag: [
|
|
t.operator,
|
|
t.operatorKeyword,
|
|
t.url,
|
|
t.escape,
|
|
t.regexp,
|
|
t.special(t.string),
|
|
],
|
|
color: colors.keyword,
|
|
},
|
|
{ tag: [t.meta, t.comment], color: colors.comment, fontStyle: "italic" },
|
|
{ tag: t.strong, fontWeight: "bold" },
|
|
{ tag: t.emphasis, fontStyle: "italic" },
|
|
{ tag: t.strikethrough, textDecoration: "line-through" },
|
|
{ tag: t.link, color: colors.function, textDecoration: "underline" },
|
|
{ tag: t.heading, fontWeight: "bold", color: colors.heading },
|
|
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: colors.number },
|
|
{
|
|
tag: [t.processingInstruction, t.string, t.inserted],
|
|
color: colors.string,
|
|
},
|
|
{ tag: t.invalid, color: "#ff5c57" },
|
|
]);
|
|
|
|
return [theme, syntaxHighlighting(highlightStyle, { fallback: true })];
|
|
}
|