✨ Added preset theme
This commit is contained in:
@@ -1191,9 +1191,20 @@ export class Theme {
|
||||
}
|
||||
|
||||
/**
|
||||
* ThemeColorConfig 主题颜色配置
|
||||
* ThemeColorConfig 主题颜色配置(与前端 ThemeColors 接口保持一致)
|
||||
*/
|
||||
export class ThemeColorConfig {
|
||||
/**
|
||||
* 主题基本信息
|
||||
* 主题名称
|
||||
*/
|
||||
"name": string;
|
||||
|
||||
/**
|
||||
* 是否为深色主题
|
||||
*/
|
||||
"dark": boolean;
|
||||
|
||||
/**
|
||||
* 基础色调
|
||||
* 主背景色
|
||||
@@ -1201,7 +1212,7 @@ export class ThemeColorConfig {
|
||||
"background": string;
|
||||
|
||||
/**
|
||||
* 次要背景色
|
||||
* 次要背景色(用于代码块交替背景)
|
||||
*/
|
||||
"backgroundSecondary": string;
|
||||
|
||||
@@ -1211,6 +1222,17 @@ export class ThemeColorConfig {
|
||||
"surface": string;
|
||||
|
||||
/**
|
||||
* 下拉菜单背景
|
||||
*/
|
||||
"dropdownBackground": string;
|
||||
|
||||
/**
|
||||
* 下拉菜单边框
|
||||
*/
|
||||
"dropdownBorder": string;
|
||||
|
||||
/**
|
||||
* 文本颜色
|
||||
* 主文本色
|
||||
*/
|
||||
"foreground": string;
|
||||
@@ -1221,12 +1243,12 @@ export class ThemeColorConfig {
|
||||
"foregroundSecondary": string;
|
||||
|
||||
/**
|
||||
* 语法高亮
|
||||
* 注释色
|
||||
*/
|
||||
"comment": string;
|
||||
|
||||
/**
|
||||
* 语法高亮色 - 核心
|
||||
* 关键字
|
||||
*/
|
||||
"keyword": string;
|
||||
@@ -1261,6 +1283,42 @@ export class ThemeColorConfig {
|
||||
*/
|
||||
"type": string;
|
||||
|
||||
/**
|
||||
* 语法高亮色 - 扩展
|
||||
* 常量
|
||||
*/
|
||||
"constant": string;
|
||||
|
||||
/**
|
||||
* 存储类型(如 static, const)
|
||||
*/
|
||||
"storage": string;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
"parameter": string;
|
||||
|
||||
/**
|
||||
* 类名
|
||||
*/
|
||||
"class": string;
|
||||
|
||||
/**
|
||||
* 标题(Markdown等)
|
||||
*/
|
||||
"heading": string;
|
||||
|
||||
/**
|
||||
* 无效内容/错误
|
||||
*/
|
||||
"invalid": string;
|
||||
|
||||
/**
|
||||
* 正则表达式
|
||||
*/
|
||||
"regexp": string;
|
||||
|
||||
/**
|
||||
* 界面元素
|
||||
* 光标
|
||||
@@ -1288,12 +1346,12 @@ export class ThemeColorConfig {
|
||||
"lineNumber": string;
|
||||
|
||||
/**
|
||||
* 活动行号
|
||||
* 活动行号颜色
|
||||
*/
|
||||
"activeLineNumber": string;
|
||||
|
||||
/**
|
||||
* 边框分割线
|
||||
* 边框和分割线
|
||||
* 边框色
|
||||
*/
|
||||
"borderColor": string;
|
||||
@@ -1304,7 +1362,7 @@ export class ThemeColorConfig {
|
||||
"borderLight": string;
|
||||
|
||||
/**
|
||||
* 搜索匹配
|
||||
* 搜索和匹配
|
||||
* 搜索匹配
|
||||
*/
|
||||
"searchMatch": string;
|
||||
@@ -1316,6 +1374,12 @@ export class ThemeColorConfig {
|
||||
|
||||
/** Creates a new ThemeColorConfig instance. */
|
||||
constructor($$source: Partial<ThemeColorConfig> = {}) {
|
||||
if (!("name" in $$source)) {
|
||||
this["name"] = "";
|
||||
}
|
||||
if (!("dark" in $$source)) {
|
||||
this["dark"] = false;
|
||||
}
|
||||
if (!("background" in $$source)) {
|
||||
this["background"] = "";
|
||||
}
|
||||
@@ -1325,6 +1389,12 @@ export class ThemeColorConfig {
|
||||
if (!("surface" in $$source)) {
|
||||
this["surface"] = "";
|
||||
}
|
||||
if (!("dropdownBackground" in $$source)) {
|
||||
this["dropdownBackground"] = "";
|
||||
}
|
||||
if (!("dropdownBorder" in $$source)) {
|
||||
this["dropdownBorder"] = "";
|
||||
}
|
||||
if (!("foreground" in $$source)) {
|
||||
this["foreground"] = "";
|
||||
}
|
||||
@@ -1355,6 +1425,27 @@ export class ThemeColorConfig {
|
||||
if (!("type" in $$source)) {
|
||||
this["type"] = "";
|
||||
}
|
||||
if (!("constant" in $$source)) {
|
||||
this["constant"] = "";
|
||||
}
|
||||
if (!("storage" in $$source)) {
|
||||
this["storage"] = "";
|
||||
}
|
||||
if (!("parameter" in $$source)) {
|
||||
this["parameter"] = "";
|
||||
}
|
||||
if (!("class" in $$source)) {
|
||||
this["class"] = "";
|
||||
}
|
||||
if (!("heading" in $$source)) {
|
||||
this["heading"] = "";
|
||||
}
|
||||
if (!("invalid" in $$source)) {
|
||||
this["invalid"] = "";
|
||||
}
|
||||
if (!("regexp" in $$source)) {
|
||||
this["regexp"] = "";
|
||||
}
|
||||
if (!("cursor" in $$source)) {
|
||||
this["cursor"] = "";
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ export function GetAllThemes(): Promise<(models$0.Theme | null)[]> & { cancel():
|
||||
}
|
||||
|
||||
/**
|
||||
* GetDefaultThemes 获取默认主题
|
||||
* GetThemeByID 根据ID获取主题
|
||||
*/
|
||||
export function GetDefaultThemes(): Promise<{ [_: string]: models$0.Theme | null }> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(3801788118) as any;
|
||||
export function GetThemeByID(id: number): Promise<models$0.Theme | null> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(3053137052, id) as any;
|
||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
||||
return $$createType3($result);
|
||||
return $$createType1($result);
|
||||
}) as any;
|
||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||
return $typingPromise;
|
||||
@@ -66,10 +66,22 @@ export function GetThemeByType(themeType: models$0.ThemeType): Promise<models$0.
|
||||
}
|
||||
|
||||
/**
|
||||
* ResetThemeColors 重置主题颜色为默认值
|
||||
* GetThemesByType 根据类型获取所有主题
|
||||
*/
|
||||
export function ResetThemeColors(themeType: models$0.ThemeType): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(342461245, themeType) as any;
|
||||
export function GetThemesByType(themeType: models$0.ThemeType): Promise<(models$0.Theme | null)[]> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(1478417492, themeType) as any;
|
||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
||||
return $$createType2($result);
|
||||
}) as any;
|
||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||
return $typingPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResetTheme 重置主题为预设配置
|
||||
*/
|
||||
export function ResetTheme(id: number): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(1806334457, id) as any;
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
@@ -90,10 +102,10 @@ export function ServiceStartup(options: application$0.ServiceOptions): Promise<v
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdateThemeColors 更新主题颜色
|
||||
* UpdateTheme 更新主题
|
||||
*/
|
||||
export function UpdateThemeColors(themeType: models$0.ThemeType, colors: models$0.ThemeColorConfig): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(2750902529, themeType, colors) as any;
|
||||
export function UpdateTheme(id: number, colors: models$0.ThemeColorConfig): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(70189749, id, colors) as any;
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
@@ -101,4 +113,3 @@ export function UpdateThemeColors(themeType: models$0.ThemeType, colors: models$
|
||||
const $$createType0 = models$0.Theme.createFrom;
|
||||
const $$createType1 = $Create.Nullable($$createType0);
|
||||
const $$createType2 = $Create.Array($$createType1);
|
||||
const $$createType3 = $Create.Map($Create.Any, $$createType1);
|
||||
|
||||
225
frontend/package-lock.json
generated
225
frontend/package-lock.json
generated
@@ -36,9 +36,9 @@
|
||||
"@codemirror/lint": "^6.9.0",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.5",
|
||||
"@codemirror/view": "^6.38.6",
|
||||
"@cospaia/prettier-plugin-clojure": "^0.0.2",
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.2",
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@prettier/plugin-xml": "^3.4.2",
|
||||
"@replit/codemirror-lang-svelte": "^6.0.0",
|
||||
@@ -62,23 +62,23 @@
|
||||
"vue": "^3.5.22",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-pick-colors": "^1.8.0",
|
||||
"vue-router": "^4.5.1"
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@eslint/js": "^9.38.0",
|
||||
"@lezer/generator": "^1.8.0",
|
||||
"@types/node": "^24.7.1",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/remarkable": "^2.0.8",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@wailsio/runtime": "latest",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-plugin-vue": "^10.5.0",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-plugin-vue": "^10.5.1",
|
||||
"globals": "^16.4.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.0",
|
||||
"typescript-eslint": "^8.46.1",
|
||||
"unplugin-vue-components": "^29.1.0",
|
||||
"vite": "^7.1.9",
|
||||
"vite": "^7.1.10",
|
||||
"vite-plugin-node-polyfills": "^0.24.0",
|
||||
"vue-eslint-parser": "^10.2.0",
|
||||
"vue-tsc": "^3.1.1"
|
||||
@@ -554,9 +554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.38.5",
|
||||
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.38.5.tgz",
|
||||
"integrity": "sha512-SFVsNAgsAoou+BjRewMqN+m9jaztB9wCWN9RSRgePqUbq8UVlvJfku5zB2KVhLPgH/h0RLk38tvd4tGeAhygnw==",
|
||||
"version": "6.38.6",
|
||||
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.38.6.tgz",
|
||||
"integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
@@ -1046,13 +1046,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-array": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.0.tgz",
|
||||
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.1.tgz",
|
||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^2.1.6",
|
||||
"@eslint/object-schema": "^2.1.7",
|
||||
"debug": "^4.3.1",
|
||||
"minimatch": "^3.1.2"
|
||||
},
|
||||
@@ -1061,9 +1061,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/config-helpers": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
|
||||
"integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.1.tgz",
|
||||
"integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -1124,9 +1124,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.37.0.tgz",
|
||||
"integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.38.0.tgz",
|
||||
"integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1137,9 +1137,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/object-schema": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.6.tgz",
|
||||
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
@@ -1320,9 +1320,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/@lezer/common/-/common-1.2.3.tgz",
|
||||
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/@lezer/common/-/common-1.3.0.tgz",
|
||||
"integrity": "sha512-L9X8uHCYU310o99L3/MpJKYxPzXPOS7S0NmBaM7UO/x2Kb2WbmMLSkfvdr1KxRIFYOpbY0Jhn7CfLSUDzL8arQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/cpp": {
|
||||
@@ -1373,12 +1373,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/@lezer/highlight/-/highlight-1.2.2.tgz",
|
||||
"integrity": "sha512-z8TQwaBXXQIvG6i2g3e9cgMwUUXu9Ib7jo2qRRggdhwKpM56Dw3PM3wmexn+EGaaOZ7az0K7sjc3/gcGW7sz7A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
"@lezer/common": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/html": {
|
||||
@@ -2327,9 +2327,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.7.1",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-24.7.1.tgz",
|
||||
"integrity": "sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==",
|
||||
"version": "24.8.1",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-24.8.1.tgz",
|
||||
"integrity": "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2344,17 +2344,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
|
||||
"integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz",
|
||||
"integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.0",
|
||||
"@typescript-eslint/type-utils": "8.46.0",
|
||||
"@typescript-eslint/utils": "8.46.0",
|
||||
"@typescript-eslint/visitor-keys": "8.46.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/type-utils": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^7.0.0",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -2368,7 +2368,7 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.46.0",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"eslint": "^8.57.0 || ^9.0.0",
|
||||
"typescript": ">=4.8.4 <6.0.0"
|
||||
}
|
||||
@@ -2384,16 +2384,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.46.0.tgz",
|
||||
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.46.1.tgz",
|
||||
"integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/typescript-estree": "8.46.0",
|
||||
"@typescript-eslint/visitor-keys": "8.46.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2409,14 +2409,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
|
||||
"integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.46.1.tgz",
|
||||
"integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.0",
|
||||
"@typescript-eslint/types": "^8.46.0",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.46.1",
|
||||
"@typescript-eslint/types": "^8.46.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2431,14 +2431,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
|
||||
"integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz",
|
||||
"integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/visitor-keys": "8.46.0"
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2449,9 +2449,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
|
||||
"integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2466,15 +2466,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
|
||||
"integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz",
|
||||
"integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/typescript-estree": "8.46.0",
|
||||
"@typescript-eslint/utils": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^2.1.0"
|
||||
},
|
||||
@@ -2491,9 +2491,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.46.0.tgz",
|
||||
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.46.1.tgz",
|
||||
"integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2505,16 +2505,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
|
||||
"integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz",
|
||||
"integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.46.0",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/visitor-keys": "8.46.0",
|
||||
"@typescript-eslint/project-service": "8.46.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/visitor-keys": "8.46.1",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -2560,16 +2560,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.46.0.tgz",
|
||||
"integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.46.1.tgz",
|
||||
"integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.7.0",
|
||||
"@typescript-eslint/scope-manager": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/typescript-estree": "8.46.0"
|
||||
"@typescript-eslint/scope-manager": "8.46.1",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2584,13 +2584,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
|
||||
"integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz",
|
||||
"integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.1",
|
||||
"eslint-visitor-keys": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3997,25 +3997,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.37.0",
|
||||
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.37.0.tgz",
|
||||
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
|
||||
"version": "9.38.0",
|
||||
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.38.0.tgz",
|
||||
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
"@eslint/config-array": "^0.21.0",
|
||||
"@eslint/config-helpers": "^0.4.0",
|
||||
"@eslint/config-array": "^0.21.1",
|
||||
"@eslint/config-helpers": "^0.4.1",
|
||||
"@eslint/core": "^0.16.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "9.37.0",
|
||||
"@eslint/js": "9.38.0",
|
||||
"@eslint/plugin-kit": "^0.4.0",
|
||||
"@humanfs/node": "^0.16.6",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
@@ -4058,9 +4057,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-10.5.0.tgz",
|
||||
"integrity": "sha512-7BZHsG3kC2vei8F2W8hnfDi9RK+cv5eKPMvzBdrl8Vuc0hR5odGQRli8VVzUkrmUHkxFEm4Iio1r5HOKslO0Aw==",
|
||||
"version": "10.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-10.5.1.tgz",
|
||||
"integrity": "sha512-SbR9ZBUFKgvWAbq3RrdCtWaW0IKm6wwUiApxf3BVTNfqUIo4IQQmreMg2iHFJJ6C/0wss3LXURBJ1OwS/MhFcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6652,16 +6651,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.46.0",
|
||||
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.46.0.tgz",
|
||||
"integrity": "sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==",
|
||||
"version": "8.46.1",
|
||||
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.46.1.tgz",
|
||||
"integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.46.0",
|
||||
"@typescript-eslint/parser": "8.46.0",
|
||||
"@typescript-eslint/typescript-estree": "8.46.0",
|
||||
"@typescript-eslint/utils": "8.46.0"
|
||||
"@typescript-eslint/eslint-plugin": "8.46.1",
|
||||
"@typescript-eslint/parser": "8.46.1",
|
||||
"@typescript-eslint/typescript-estree": "8.46.1",
|
||||
"@typescript-eslint/utils": "8.46.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -7029,9 +7028,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.1.9",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-7.1.9.tgz",
|
||||
"integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==",
|
||||
"version": "7.1.10",
|
||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-7.1.10.tgz",
|
||||
"integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -7250,9 +7249,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz",
|
||||
"integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==",
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.3.tgz",
|
||||
"integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.6.4"
|
||||
@@ -7261,7 +7260,7 @@
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.0"
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router/node_modules/@vue/devtools-api": {
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
"@codemirror/lint": "^6.9.0",
|
||||
"@codemirror/search": "^6.5.11",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.5",
|
||||
"@codemirror/view": "^6.38.6",
|
||||
"@cospaia/prettier-plugin-clojure": "^0.0.2",
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.2",
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@prettier/plugin-xml": "^3.4.2",
|
||||
"@replit/codemirror-lang-svelte": "^6.0.0",
|
||||
@@ -67,23 +67,23 @@
|
||||
"vue": "^3.5.22",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-pick-colors": "^1.8.0",
|
||||
"vue-router": "^4.5.1"
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@eslint/js": "^9.38.0",
|
||||
"@lezer/generator": "^1.8.0",
|
||||
"@types/node": "^24.7.1",
|
||||
"@types/node": "^24.8.1",
|
||||
"@types/remarkable": "^2.0.8",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@wailsio/runtime": "latest",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-plugin-vue": "^10.5.0",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-plugin-vue": "^10.5.1",
|
||||
"globals": "^16.4.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.0",
|
||||
"typescript-eslint": "^8.46.1",
|
||||
"unplugin-vue-components": "^29.1.0",
|
||||
"vite": "^7.1.9",
|
||||
"vite": "^7.1.10",
|
||||
"vite-plugin-node-polyfills": "^0.24.0",
|
||||
"vue-eslint-parser": "^10.2.0",
|
||||
"vue-tsc": "^3.1.1"
|
||||
|
||||
@@ -166,12 +166,17 @@ export default {
|
||||
interface: 'Interface Elements',
|
||||
border: 'Borders & Dividers',
|
||||
search: 'Search & Matching',
|
||||
// Base Colors
|
||||
background: 'Main Background',
|
||||
backgroundSecondary: 'Secondary Background',
|
||||
surface: 'Panel Background',
|
||||
dropdownBackground: 'Dropdown Background',
|
||||
dropdownBorder: 'Dropdown Border',
|
||||
// Text Colors
|
||||
foreground: 'Primary Text',
|
||||
foregroundSecondary: 'Secondary Text',
|
||||
comment: 'Comments',
|
||||
// Syntax Highlighting - Core
|
||||
keyword: 'Keywords',
|
||||
string: 'Strings',
|
||||
function: 'Functions',
|
||||
@@ -179,14 +184,25 @@ export default {
|
||||
operator: 'Operators',
|
||||
variable: 'Variables',
|
||||
type: 'Types',
|
||||
// Syntax Highlighting - Extended
|
||||
constant: 'Constants',
|
||||
storage: 'Storage Type',
|
||||
parameter: 'Parameters',
|
||||
class: 'Class Names',
|
||||
heading: 'Headings',
|
||||
invalid: 'Invalid/Error',
|
||||
regexp: 'Regular Expressions',
|
||||
// Interface Elements
|
||||
cursor: 'Cursor',
|
||||
selection: 'Selection Background',
|
||||
selectionBlur: 'Unfocused Selection',
|
||||
activeLine: 'Active Line Highlight',
|
||||
lineNumber: 'Line Numbers',
|
||||
activeLineNumber: 'Active Line Number',
|
||||
// Borders & Dividers
|
||||
borderColor: 'Border Color',
|
||||
borderLight: 'Light Border',
|
||||
// Search & Matching
|
||||
searchMatch: 'Search Match',
|
||||
matchingBracket: 'Matching Bracket'
|
||||
},
|
||||
@@ -199,6 +215,7 @@ export default {
|
||||
enableTabIndent: 'Enable Tab Indent',
|
||||
language: 'Interface Language',
|
||||
systemTheme: 'System Theme',
|
||||
presetTheme: 'Preset Theme',
|
||||
saveOptions: 'Save Options',
|
||||
autoSaveDelay: 'Auto Save Delay (ms)',
|
||||
updateSettings: 'Update Settings',
|
||||
|
||||
@@ -166,6 +166,7 @@ export default {
|
||||
enableTabIndent: '启用 Tab 缩进',
|
||||
language: '界面语言',
|
||||
systemTheme: '系统主题',
|
||||
presetTheme: '预设主题',
|
||||
saveOptions: '保存选项',
|
||||
autoSaveDelay: '自动保存延迟(毫秒)',
|
||||
updateSettings: '更新设置',
|
||||
@@ -206,12 +207,17 @@ export default {
|
||||
interface: '界面元素',
|
||||
border: '边框分割线',
|
||||
search: '搜索匹配',
|
||||
// 基础色调
|
||||
background: '主背景色',
|
||||
backgroundSecondary: '次要背景色',
|
||||
surface: '面板背景',
|
||||
dropdownBackground: '下拉菜单背景',
|
||||
dropdownBorder: '下拉菜单边框',
|
||||
// 文本颜色
|
||||
foreground: '主文本色',
|
||||
foregroundSecondary: '次要文本色',
|
||||
comment: '注释色',
|
||||
// 语法高亮 - 核心
|
||||
keyword: '关键字',
|
||||
string: '字符串',
|
||||
function: '函数名',
|
||||
@@ -219,14 +225,25 @@ export default {
|
||||
operator: '操作符',
|
||||
variable: '变量',
|
||||
type: '类型',
|
||||
// 语法高亮 - 扩展
|
||||
constant: '常量',
|
||||
storage: '存储类型',
|
||||
parameter: '参数',
|
||||
class: '类名',
|
||||
heading: '标题',
|
||||
invalid: '无效内容',
|
||||
regexp: '正则表达式',
|
||||
// 界面元素
|
||||
cursor: '光标',
|
||||
selection: '选中背景',
|
||||
selectionBlur: '失焦选中背景',
|
||||
activeLine: '当前行高亮',
|
||||
lineNumber: '行号',
|
||||
activeLineNumber: '活动行号',
|
||||
// 边框和分割线
|
||||
borderColor: '边框色',
|
||||
borderLight: '浅色边框',
|
||||
// 搜索和匹配
|
||||
searchMatch: '搜索匹配',
|
||||
matchingBracket: '匹配括号'
|
||||
},
|
||||
|
||||
@@ -1,33 +1,59 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { SystemThemeType, ThemeType, ThemeColorConfig } from '@/../bindings/voidraft/internal/models/models';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import {SystemThemeType, ThemeType, Theme, ThemeColorConfig} from '@/../bindings/voidraft/internal/models/models';
|
||||
import { ThemeService } from '@/../bindings/voidraft/internal/services';
|
||||
import { useConfigStore } from './configStore';
|
||||
import { useEditorStore } from './editorStore';
|
||||
import { defaultDarkColors } from '@/views/editor/theme/dark';
|
||||
import { defaultLightColors } from '@/views/editor/theme/light';
|
||||
import type { ThemeColors } from '@/views/editor/theme/types';
|
||||
import { getThemeConfig } from '@/views/editor/theme/registry';
|
||||
|
||||
/**
|
||||
* 主题管理 Store
|
||||
* 职责:管理主题状态和颜色配置
|
||||
* 职责:管理主题状态、颜色配置和预设主题列表
|
||||
*/
|
||||
export const useThemeStore = defineStore('theme', () => {
|
||||
const configStore = useConfigStore();
|
||||
|
||||
// 响应式状态
|
||||
const themeColors = reactive({
|
||||
darkTheme: { ...defaultDarkColors },
|
||||
lightTheme: { ...defaultLightColors }
|
||||
// 所有主题列表(从数据库加载)
|
||||
const allThemes = ref<Theme[]>([]);
|
||||
|
||||
// 当前选中的主题 ID
|
||||
const currentThemeIds = reactive({
|
||||
dark: 0, // 当前深色主题ID
|
||||
light: 0, // 当前浅色主题ID
|
||||
});
|
||||
|
||||
// 计算属性
|
||||
// 当前主题的颜色配置(用于编辑器渲染)
|
||||
const currentColors = reactive<{
|
||||
dark: ThemeColors | null;
|
||||
light: ThemeColors | null;
|
||||
}>({
|
||||
dark: null,
|
||||
light: null,
|
||||
});
|
||||
|
||||
// 计算属性:当前系统主题模式
|
||||
const currentTheme = computed(() =>
|
||||
configStore.config?.appearance?.systemTheme || SystemThemeType.SystemThemeAuto
|
||||
);
|
||||
|
||||
// 获取默认主题颜色
|
||||
const getDefaultColors = (themeType: ThemeType) =>
|
||||
themeType === ThemeType.ThemeTypeDark ? defaultDarkColors : defaultLightColors;
|
||||
// 计算属性:根据类型获取主题列表
|
||||
const darkThemes = computed(() =>
|
||||
allThemes.value.filter(t => t.type === ThemeType.ThemeTypeDark)
|
||||
);
|
||||
|
||||
const lightThemes = computed(() =>
|
||||
allThemes.value.filter(t => t.type === ThemeType.ThemeTypeLight)
|
||||
);
|
||||
|
||||
// 计算属性:获取当前激活的主题对象
|
||||
const activeTheme = computed(() => {
|
||||
const isDark = currentTheme.value === SystemThemeType.SystemThemeDark ||
|
||||
(currentTheme.value === SystemThemeType.SystemThemeAuto &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
|
||||
return isDark ? currentColors.dark : currentColors.light;
|
||||
});
|
||||
|
||||
// 应用主题到 DOM
|
||||
const applyThemeToDOM = (theme: SystemThemeType) => {
|
||||
@@ -39,30 +65,77 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
document.documentElement.setAttribute('data-theme', themeMap[theme]);
|
||||
};
|
||||
|
||||
// 初始化主题颜色
|
||||
// 从数据库加载所有主题
|
||||
const loadAllThemes = async () => {
|
||||
try {
|
||||
const themes = await ThemeService.GetAllThemes();
|
||||
allThemes.value = (themes || []).filter((t): t is Theme => t !== null);
|
||||
return allThemes.value;
|
||||
} catch (error) {
|
||||
console.error('Failed to load themes from database:', error);
|
||||
allThemes.value = [];
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// 根据主题对象加载颜色配置
|
||||
const loadThemeColors = (theme: Theme): ThemeColors => {
|
||||
// 优先使用数据库中的颜色配置
|
||||
const dbColors = theme.colors as unknown as ThemeColors;
|
||||
|
||||
// 如果数据库颜色不完整,尝试从预设主题获取
|
||||
if (!dbColors || Object.keys(dbColors).length < 10) {
|
||||
const presetConfig = getThemeConfig(theme.name);
|
||||
if (presetConfig) {
|
||||
return presetConfig;
|
||||
}
|
||||
}
|
||||
|
||||
return dbColors;
|
||||
};
|
||||
|
||||
// 初始化主题颜色(加载默认主题)
|
||||
const initializeThemeColors = async () => {
|
||||
try {
|
||||
const themes = await ThemeService.GetDefaultThemes();
|
||||
// 加载所有主题
|
||||
await loadAllThemes();
|
||||
|
||||
// 如果没有获取到主题数据,使用默认值
|
||||
if (!themes) {
|
||||
Object.assign(themeColors.darkTheme, defaultDarkColors);
|
||||
Object.assign(themeColors.lightTheme, defaultLightColors);
|
||||
return;
|
||||
// 查找默认主题
|
||||
const defaultDark = allThemes.value.find(
|
||||
t => t.type === ThemeType.ThemeTypeDark && t.isDefault
|
||||
);
|
||||
const defaultLight = allThemes.value.find(
|
||||
t => t.type === ThemeType.ThemeTypeLight && t.isDefault
|
||||
);
|
||||
|
||||
// 设置默认主题
|
||||
if (defaultDark) {
|
||||
currentThemeIds.dark = defaultDark.id;
|
||||
currentColors.dark = loadThemeColors(defaultDark);
|
||||
}
|
||||
|
||||
// 更新主题颜色
|
||||
if (themes[ThemeType.ThemeTypeDark]) {
|
||||
Object.assign(themeColors.darkTheme, themes[ThemeType.ThemeTypeDark].colors);
|
||||
if (defaultLight) {
|
||||
currentThemeIds.light = defaultLight.id;
|
||||
currentColors.light = loadThemeColors(defaultLight);
|
||||
}
|
||||
if (themes[ThemeType.ThemeTypeLight]) {
|
||||
Object.assign(themeColors.lightTheme, themes[ThemeType.ThemeTypeLight].colors);
|
||||
|
||||
// 如果没有找到默认主题,使用第一个可用主题
|
||||
if (!currentColors.dark && darkThemes.value.length > 0) {
|
||||
const fallback = darkThemes.value[0];
|
||||
currentThemeIds.dark = fallback.id;
|
||||
currentColors.dark = loadThemeColors(fallback);
|
||||
}
|
||||
|
||||
if (!currentColors.light && lightThemes.value.length > 0) {
|
||||
const fallback = lightThemes.value[0];
|
||||
currentThemeIds.light = fallback.id;
|
||||
currentColors.light = loadThemeColors(fallback);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load themes from database, using defaults:', error);
|
||||
// 如果数据库加载失败,使用默认主题
|
||||
Object.assign(themeColors.darkTheme, defaultDarkColors);
|
||||
Object.assign(themeColors.lightTheme, defaultLightColors);
|
||||
console.error('Failed to initialize theme colors:', error);
|
||||
// 使用预设主题作为后备
|
||||
currentColors.dark = getThemeConfig('default-dark');
|
||||
currentColors.light = getThemeConfig('default-light');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,77 +146,109 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
await initializeThemeColors();
|
||||
};
|
||||
|
||||
// 设置主题
|
||||
// 设置系统主题模式(深色/浅色/自动)
|
||||
const setTheme = async (theme: SystemThemeType) => {
|
||||
await configStore.setSystemTheme(theme);
|
||||
applyThemeToDOM(theme);
|
||||
refreshEditorTheme();
|
||||
};
|
||||
|
||||
// 更新主题颜色 - 合并逻辑,减少重复代码
|
||||
const updateThemeColors = (darkColors?: any, lightColors?: any): boolean => {
|
||||
let hasChanges = false;
|
||||
|
||||
const updateColors = (target: any, source: any) => {
|
||||
if (!source) return false;
|
||||
|
||||
let changed = false;
|
||||
Object.entries(source).forEach(([key, value]) => {
|
||||
if (value !== undefined && target[key] !== value) {
|
||||
target[key] = value;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
return changed;
|
||||
};
|
||||
|
||||
hasChanges = updateColors(themeColors.darkTheme, darkColors) || hasChanges;
|
||||
hasChanges = updateColors(themeColors.lightTheme, lightColors) || hasChanges;
|
||||
|
||||
return hasChanges;
|
||||
};
|
||||
|
||||
// 保存主题颜色到数据库
|
||||
const saveThemeColors = async () => {
|
||||
// 切换到指定的预设主题(通过主题ID)
|
||||
const switchToTheme = async (themeId: number) => {
|
||||
try {
|
||||
const darkColors = ThemeColorConfig.createFrom(themeColors.darkTheme);
|
||||
const lightColors = ThemeColorConfig.createFrom(themeColors.lightTheme);
|
||||
const theme = allThemes.value.find(t => t.id === themeId);
|
||||
if (!theme) {
|
||||
console.error('Theme not found:', themeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
ThemeService.UpdateThemeColors(ThemeType.ThemeTypeDark, darkColors),
|
||||
ThemeService.UpdateThemeColors(ThemeType.ThemeTypeLight, lightColors)
|
||||
]);
|
||||
// 加载主题颜色
|
||||
const colors = loadThemeColors(theme);
|
||||
|
||||
// 根据主题类型更新对应的颜色配置
|
||||
if (theme.type === ThemeType.ThemeTypeDark) {
|
||||
currentThemeIds.dark = themeId;
|
||||
currentColors.dark = colors;
|
||||
} else {
|
||||
currentThemeIds.light = themeId;
|
||||
currentColors.light = colors;
|
||||
}
|
||||
|
||||
// 刷新编辑器主题
|
||||
refreshEditorTheme();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to save theme colors:', error);
|
||||
console.error('Failed to switch theme:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 更新当前主题的颜色配置
|
||||
const updateCurrentColors = (colors: Partial<ThemeColors>, isDark: boolean) => {
|
||||
const target = isDark ? currentColors.dark : currentColors.light;
|
||||
if (!target) return;
|
||||
|
||||
Object.assign(target, colors);
|
||||
};
|
||||
|
||||
// 保存当前主题颜色到数据库
|
||||
const saveCurrentTheme = async (isDark: boolean) => {
|
||||
try {
|
||||
const themeId = isDark ? currentThemeIds.dark : currentThemeIds.light;
|
||||
const colors = isDark ? currentColors.dark : currentColors.light;
|
||||
|
||||
if (!themeId || !colors) {
|
||||
throw new Error('No theme selected');
|
||||
}
|
||||
|
||||
// 转换为数据库格式并保存
|
||||
const dbColors = colors as ThemeColorConfig; // ThemeColorConfig from bindings
|
||||
await ThemeService.UpdateTheme(themeId, dbColors);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to save theme:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置主题颜色
|
||||
const resetThemeColors = async (themeType: 'darkTheme' | 'lightTheme') => {
|
||||
// 重置当前主题为预设配置
|
||||
const resetCurrentTheme = async (isDark: boolean) => {
|
||||
try {
|
||||
const dbThemeType = themeType === 'darkTheme' ? ThemeType.ThemeTypeDark : ThemeType.ThemeTypeLight;
|
||||
const themeId = isDark ? currentThemeIds.dark : currentThemeIds.light;
|
||||
|
||||
// 1. 调用后端重置服务
|
||||
await ThemeService.ResetThemeColors(dbThemeType);
|
||||
if (!themeId) {
|
||||
throw new Error('No theme selected');
|
||||
}
|
||||
|
||||
// 2. 更新内存中的颜色状态
|
||||
const defaultColors = getDefaultColors(dbThemeType);
|
||||
Object.assign(themeColors[themeType], defaultColors);
|
||||
// 调用后端重置服务
|
||||
await ThemeService.ResetTheme(themeId);
|
||||
|
||||
// 3. 刷新编辑器主题
|
||||
// 重新加载主题
|
||||
await loadAllThemes();
|
||||
const theme = allThemes.value.find(t => t.id === themeId);
|
||||
|
||||
if (theme) {
|
||||
const colors = loadThemeColors(theme);
|
||||
if (isDark) {
|
||||
currentColors.dark = colors;
|
||||
} else {
|
||||
currentColors.light = colors;
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新编辑器主题
|
||||
refreshEditorTheme();
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to reset theme colors:', error);
|
||||
console.error('Failed to reset theme:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 刷新编辑器主题
|
||||
const refreshEditorTheme = () => {
|
||||
// 使用当前主题重新应用DOM主题
|
||||
applyThemeToDOM(currentTheme.value);
|
||||
|
||||
const editorStore = useEditorStore();
|
||||
@@ -151,14 +256,24 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
};
|
||||
|
||||
return {
|
||||
// 状态
|
||||
allThemes,
|
||||
darkThemes,
|
||||
lightThemes,
|
||||
currentTheme,
|
||||
themeColors,
|
||||
currentThemeIds,
|
||||
currentColors,
|
||||
activeTheme,
|
||||
|
||||
// 方法
|
||||
setTheme,
|
||||
switchToTheme,
|
||||
initializeTheme,
|
||||
loadAllThemes,
|
||||
updateCurrentColors,
|
||||
saveCurrentTheme,
|
||||
resetCurrentTheme,
|
||||
refreshEditorTheme,
|
||||
applyThemeToDOM,
|
||||
updateThemeColors,
|
||||
saveThemeColors,
|
||||
resetThemeColors,
|
||||
refreshEditorTheme
|
||||
};
|
||||
});
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Extension, Compartment } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { SystemThemeType } from '@/../bindings/voidraft/internal/models/models';
|
||||
import { createDarkTheme } from '@/views/editor/theme/dark';
|
||||
import { createLightTheme } from '@/views/editor/theme/light';
|
||||
import { createThemeByColors } from '@/views/editor/theme/registry';
|
||||
import { useThemeStore } from '@/stores/themeStore';
|
||||
|
||||
// 主题区间 - 用于动态切换主题
|
||||
@@ -11,23 +10,25 @@ export const themeCompartment = new Compartment();
|
||||
/**
|
||||
* 根据主题类型获取主题扩展
|
||||
*/
|
||||
const getThemeExtension = (themeType: SystemThemeType): Extension => {
|
||||
const getThemeExtension = (themeType: SystemThemeType): Extension | null => {
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
// 处理 auto 主题类型
|
||||
let actualTheme: SystemThemeType = themeType;
|
||||
let isDark = themeType === SystemThemeType.SystemThemeDark;
|
||||
if (themeType === SystemThemeType.SystemThemeAuto) {
|
||||
actualTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? SystemThemeType.SystemThemeDark
|
||||
: SystemThemeType.SystemThemeLight;
|
||||
isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
}
|
||||
|
||||
// 根据主题类型创建主题
|
||||
if (actualTheme === SystemThemeType.SystemThemeLight) {
|
||||
return createLightTheme(themeStore.themeColors.lightTheme);
|
||||
} else {
|
||||
return createDarkTheme(themeStore.themeColors.darkTheme);
|
||||
// 根据主题类型获取对应的颜色配置
|
||||
const colors = isDark ? themeStore.currentColors.dark : themeStore.currentColors.light;
|
||||
|
||||
if (!colors) {
|
||||
console.warn('Theme colors not loaded yet');
|
||||
return null;
|
||||
}
|
||||
|
||||
// 使用颜色配置创建主题
|
||||
return createThemeByColors(colors);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,12 @@ const getThemeExtension = (themeType: SystemThemeType): Extension => {
|
||||
*/
|
||||
export const createThemeExtension = (themeType: SystemThemeType = SystemThemeType.SystemThemeDark): Extension => {
|
||||
const extension = getThemeExtension(themeType);
|
||||
|
||||
// 如果主题未加载,返回空扩展
|
||||
if (!extension) {
|
||||
return themeCompartment.of([]);
|
||||
}
|
||||
|
||||
return themeCompartment.of(extension);
|
||||
};
|
||||
|
||||
@@ -48,6 +55,13 @@ export const updateEditorTheme = (view: EditorView, themeType: SystemThemeType):
|
||||
|
||||
try {
|
||||
const extension = getThemeExtension(themeType);
|
||||
|
||||
// 如果主题未加载,不更新
|
||||
if (!extension) {
|
||||
console.warn('Cannot update theme: theme not loaded');
|
||||
return;
|
||||
}
|
||||
|
||||
view.dispatch({
|
||||
effects: themeCompartment.reconfigure(extension)
|
||||
});
|
||||
|
||||
@@ -1,48 +1,17 @@
|
||||
import {EditorView} from '@codemirror/view';
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language';
|
||||
import {tags} from '@lezer/highlight';
|
||||
import {Extension} from '@codemirror/state';
|
||||
import type {ThemeColors} from './types';
|
||||
|
||||
// 默认深色主题颜色
|
||||
export const defaultDarkColors = {
|
||||
// 基础色调
|
||||
background: '#252B37', // 主背景色
|
||||
backgroundSecondary: '#213644', // 次要背景色
|
||||
surface: '#474747', // 面板背景
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#9BB586', // 主文本色
|
||||
foregroundSecondary: '#9c9c9c', // 次要文本色
|
||||
comment: '#6272a4', // 注释色
|
||||
|
||||
// 语法高亮色
|
||||
keyword: '#ff79c6', // 关键字
|
||||
string: '#f1fa8c', // 字符串
|
||||
function: '#50fa7b', // 函数名
|
||||
number: '#bd93f9', // 数字
|
||||
operator: '#ff79c6', // 操作符
|
||||
variable: '#8fbcbb', // 变量
|
||||
type: '#8be9fd', // 类型
|
||||
|
||||
// 界面元素
|
||||
cursor: '#ffffff', // 光标
|
||||
selection: '#0865a9', // 选中背景
|
||||
selectionBlur: '#225377', // 失焦选中背景
|
||||
activeLine: '#ffffff0a', // 当前行高亮
|
||||
lineNumber: '#ffffff26', // 行号
|
||||
activeLineNumber: '#ffffff99', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#1e222a', // 边框色
|
||||
borderLight: '#ffffff19', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#8fbcbb', // 搜索匹配
|
||||
matchingBracket: '#ffffff19', // 匹配括号
|
||||
};
|
||||
|
||||
// 创建深色主题
|
||||
export function createDarkTheme(colors = defaultDarkColors) {
|
||||
const darkTheme = EditorView.theme({
|
||||
/**
|
||||
* 创建通用主题
|
||||
* @param colors 主题颜色配置
|
||||
* @returns CodeMirror Extension数组
|
||||
*/
|
||||
export function createBaseTheme(colors: ThemeColors): Extension {
|
||||
// 编辑器主题样式
|
||||
const theme = EditorView.theme({
|
||||
'&': {
|
||||
color: colors.foreground,
|
||||
backgroundColor: colors.background,
|
||||
@@ -79,6 +48,9 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
'.cm-content ::selection': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
'.cm-activeLine.code-empty-block-selected': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
@@ -90,9 +62,10 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
|
||||
// 行号区域
|
||||
'.cm-gutters': {
|
||||
backgroundColor: 'rgba(0,0,0, 0.1)',
|
||||
backgroundColor: colors.dark ? 'rgba(0,0,0, 0.1)' : 'rgba(0,0,0, 0.04)',
|
||||
color: colors.lineNumber,
|
||||
border: 'none',
|
||||
borderRight: colors.dark ? 'none' : `1px solid ${colors.borderLight}`,
|
||||
padding: '0 2px 0 4px',
|
||||
userSelect: 'none',
|
||||
},
|
||||
@@ -115,9 +88,20 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: '#ddd',
|
||||
color: colors.comment,
|
||||
},
|
||||
|
||||
// 面板
|
||||
'.cm-panels': {
|
||||
backgroundColor: colors.dropdownBackground,
|
||||
color: colors.foreground
|
||||
},
|
||||
'.cm-panels.cm-panels-top': {
|
||||
borderBottom: '2px solid black'
|
||||
},
|
||||
'.cm-panels.cm-panels-bottom': {
|
||||
borderTop: '2px solid black'
|
||||
},
|
||||
|
||||
// 搜索匹配
|
||||
'.cm-searchMatch': {
|
||||
@@ -125,11 +109,11 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
outline: `1px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: colors.foreground,
|
||||
backgroundColor: colors.searchMatch,
|
||||
color: colors.background,
|
||||
},
|
||||
'.cm-selectionMatch': {
|
||||
backgroundColor: '#50606D',
|
||||
backgroundColor: colors.dark ? '#50606D' : '#e6f3ff',
|
||||
},
|
||||
|
||||
// 括号匹配
|
||||
@@ -141,7 +125,7 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: '0.5px solid #bc8f8f',
|
||||
outline: colors.dark ? '0.5px solid #bc8f8f' : '0.5px solid #d73a49',
|
||||
},
|
||||
|
||||
// 编辑器焦点
|
||||
@@ -151,8 +135,10 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
|
||||
// 工具提示
|
||||
'.cm-tooltip': {
|
||||
border: 'none',
|
||||
border: colors.dark ? 'none' : `1px solid ${colors.dropdownBorder}`,
|
||||
backgroundColor: colors.surface,
|
||||
color: colors.foreground,
|
||||
boxShadow: colors.dark ? 'none' : '0 2px 8px rgba(0,0,0,0.1)',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
@@ -169,7 +155,7 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
},
|
||||
},
|
||||
|
||||
// 代码块层
|
||||
// 代码块层(自定义)
|
||||
'.code-blocks-layer': {
|
||||
width: '100%',
|
||||
},
|
||||
@@ -188,16 +174,18 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
background: colors.backgroundSecondary,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
|
||||
// 数学计算结果(自定义)
|
||||
'.code-blocks-math-result': {
|
||||
paddingLeft: "12px",
|
||||
position: "relative",
|
||||
},
|
||||
".code-blocks-math-result .inner": {
|
||||
background: "#0e1217",
|
||||
color: "#a0e7c7",
|
||||
background: colors.dark ? '#0e1217' : '#48b57e',
|
||||
color: colors.dark ? '#a0e7c7' : '#fff',
|
||||
padding: '0px 4px',
|
||||
borderRadius: '2px',
|
||||
boxShadow: '0 0 3px rgba(0,0,0, 0.3)',
|
||||
boxShadow: colors.dark ? '0 0 3px rgba(0,0,0, 0.3)' : '0 0 3px rgba(0,0,0, 0.1)',
|
||||
cursor: 'pointer',
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
@@ -209,13 +197,13 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
width: "60px",
|
||||
transition: "opacity 500ms",
|
||||
transitionDelay: "1000ms",
|
||||
color: "rgba(220,240,230, 1.0)",
|
||||
color: colors.dark ? 'rgba(220,240,230, 1.0)' : 'rgba(0,0,0, 0.8)',
|
||||
},
|
||||
'.code-blocks-math-result-copied.fade-out': {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
// 代码块开始标记
|
||||
// 代码块开始标记(自定义)
|
||||
'.code-block-start': {
|
||||
height: '12px',
|
||||
position: 'relative',
|
||||
@@ -223,47 +211,79 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
'.code-block-start.first': {
|
||||
height: '0px',
|
||||
},
|
||||
}, {dark: true});
|
||||
}, {dark: colors.dark});
|
||||
|
||||
// 语法高亮样式
|
||||
const darkHighlightStyle = HighlightStyle.define([
|
||||
const highlightStyle = HighlightStyle.define([
|
||||
// 关键字
|
||||
{tag: tags.keyword, color: colors.keyword},
|
||||
{tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: colors.variable},
|
||||
{tag: [tags.variableName], color: colors.variable},
|
||||
{tag: [tags.function(tags.variableName)], color: colors.function},
|
||||
{tag: [tags.labelName], color: colors.operator},
|
||||
{tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: colors.keyword},
|
||||
{tag: [tags.definition(tags.name), tags.separator], color: colors.function},
|
||||
{tag: [tags.brace], color: colors.variable},
|
||||
{tag: [tags.annotation], color: '#d30102'},
|
||||
{tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: colors.number},
|
||||
{tag: [tags.typeName, tags.className], color: colors.type},
|
||||
|
||||
// 操作符
|
||||
{tag: [tags.operator, tags.operatorKeyword], color: colors.operator},
|
||||
{tag: [tags.tagName], color: colors.number},
|
||||
{tag: [tags.squareBracket], color: '#bf616a'},
|
||||
{tag: [tags.angleBracket], color: '#d08770'},
|
||||
{tag: [tags.attributeName], color: colors.variable},
|
||||
{tag: [tags.regexp], color: colors.string},
|
||||
|
||||
// 名称、变量
|
||||
{tag: [tags.name, tags.deleted, tags.character, tags.macroName], color: colors.variable},
|
||||
{tag: [tags.variableName], color: colors.variable},
|
||||
{tag: [tags.labelName], color: colors.operator},
|
||||
{tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: colors.variable},
|
||||
|
||||
// 函数
|
||||
{tag: [tags.function(tags.variableName)], color: colors.function},
|
||||
{tag: [tags.propertyName], color: colors.function},
|
||||
|
||||
// 类型、类
|
||||
{tag: [tags.typeName], color: colors.type},
|
||||
{tag: [tags.className], color: colors.class},
|
||||
|
||||
// 常量
|
||||
{tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: colors.constant},
|
||||
|
||||
// 字符串
|
||||
{tag: [tags.processingInstruction, tags.string, tags.inserted], color: colors.string},
|
||||
{tag: [tags.special(tags.string)], color: colors.string},
|
||||
{tag: [tags.quote], color: colors.comment},
|
||||
{tag: [tags.string], color: colors.string},
|
||||
{tag: tags.link, color: colors.variable, textDecoration: 'underline'},
|
||||
{tag: [tags.url, tags.escape, tags.special(tags.string)], color: colors.string},
|
||||
{tag: [tags.meta], color: colors.comment},
|
||||
{tag: [tags.comment], color: colors.comment, fontStyle: 'italic'},
|
||||
|
||||
// 数字
|
||||
{tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: colors.number},
|
||||
|
||||
// 正则表达式
|
||||
{tag: [tags.url, tags.escape, tags.regexp, tags.link], color: colors.regexp},
|
||||
|
||||
// 注释
|
||||
{tag: [tags.meta, tags.comment], color: colors.comment, fontStyle: 'italic'},
|
||||
|
||||
// 分隔符、括号
|
||||
{tag: [tags.definition(tags.name), tags.separator], color: colors.variable},
|
||||
{tag: [tags.brace], color: colors.variable},
|
||||
{tag: [tags.squareBracket], color: colors.dark ? '#bf616a' : colors.keyword},
|
||||
{tag: [tags.angleBracket], color: colors.dark ? '#d08770' : colors.operator},
|
||||
{tag: [tags.attributeName], color: colors.variable},
|
||||
|
||||
// 标签
|
||||
{tag: [tags.tagName], color: colors.number},
|
||||
|
||||
// 注解
|
||||
{tag: [tags.annotation], color: colors.invalid},
|
||||
|
||||
// 特殊样式
|
||||
{tag: tags.strong, fontWeight: 'bold'},
|
||||
{tag: tags.emphasis, fontStyle: 'italic'},
|
||||
{tag: tags.strikethrough, textDecoration: 'line-through'},
|
||||
{tag: tags.heading, fontWeight: 'bold', color: colors.keyword},
|
||||
{tag: tags.link, color: colors.variable, textDecoration: 'underline'},
|
||||
|
||||
// 标题
|
||||
{tag: tags.heading, fontWeight: 'bold', color: colors.heading},
|
||||
{tag: [tags.heading1, tags.heading2], fontSize: '1.4em'},
|
||||
{tag: [tags.heading3, tags.heading4], fontSize: '1.2em'},
|
||||
{tag: [tags.heading5, tags.heading6], fontSize: '1.1em'},
|
||||
|
||||
// 无效内容
|
||||
{tag: tags.invalid, color: colors.invalid},
|
||||
]);
|
||||
|
||||
return [
|
||||
darkTheme,
|
||||
syntaxHighlighting(darkHighlightStyle),
|
||||
theme,
|
||||
syntaxHighlighting(highlightStyle),
|
||||
];
|
||||
}
|
||||
|
||||
// 默认深色主题
|
||||
export const dark = createDarkTheme(defaultDarkColors);
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
export const config: ThemeColors = {
|
||||
name: 'aura',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#21202e',
|
||||
foreground: '#edecee',
|
||||
selection: '#3d375e7f',
|
||||
cursor: '#a277ff',
|
||||
backgroundSecondary: '#21202e',
|
||||
surface: '#21202e',
|
||||
dropdownBackground: '#21202e',
|
||||
dropdownBorder: '#3b334b',
|
||||
activeLine: '#4d4b6622',
|
||||
lineNumber: '#a394f033',
|
||||
activeLineNumber: '#cdccce',
|
||||
matchingBracket: '#a394f033',
|
||||
keyword: '#a277ff',
|
||||
storage: '#a277ff',
|
||||
variable: '#edecee',
|
||||
parameter: '#edecee',
|
||||
function: '#ffca85',
|
||||
string: '#61ffca',
|
||||
constant: '#61ffca',
|
||||
type: '#82e2ff',
|
||||
class: '#82e2ff',
|
||||
number: '#61ffca',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#edecee',
|
||||
foregroundSecondary: '#edecee',
|
||||
comment: '#6d6d6d',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#a277ff',
|
||||
string: '#61ffca',
|
||||
function: '#ffca85',
|
||||
number: '#61ffca',
|
||||
operator: '#a277ff',
|
||||
variable: '#edecee',
|
||||
type: '#82e2ff',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#61ffca',
|
||||
storage: '#a277ff',
|
||||
parameter: '#edecee',
|
||||
class: '#82e2ff',
|
||||
heading: '#a277ff',
|
||||
invalid: '#ff6767',
|
||||
regexp: '#61ffca',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#a277ff',
|
||||
selection: '#3d375e7f',
|
||||
selectionBlur: '#3d375e7f',
|
||||
activeLine: '#4d4b6622',
|
||||
lineNumber: '#a394f033',
|
||||
activeLineNumber: '#cdccce',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#3b334b',
|
||||
borderLight: '#edecee19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#61ffca',
|
||||
matchingBracket: '#a394f033',
|
||||
}
|
||||
|
||||
export const auraTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const auraHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const aura: Extension = [
|
||||
auraTheme,
|
||||
syntaxHighlighting(auraHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Aura 主题
|
||||
export const aura: Extension = createBaseTheme(config)
|
||||
|
||||
63
frontend/src/views/editor/theme/dark/default-dark.ts
Normal file
63
frontend/src/views/editor/theme/dark/default-dark.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {createBaseTheme} from '../base';
|
||||
import type {ThemeColors} from '../types';
|
||||
|
||||
// 默认深色主题颜色
|
||||
export const defaultDarkColors: ThemeColors = {
|
||||
// 主题信息
|
||||
name: 'default-dark',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#252B37', // 主背景色
|
||||
backgroundSecondary: '#213644', // 次要背景色
|
||||
surface: '#474747', // 面板背景
|
||||
dropdownBackground: '#252B37', // 下拉菜单背景
|
||||
dropdownBorder: '#ffffff19', // 下拉菜单边框
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#9BB586', // 主文本色
|
||||
foregroundSecondary: '#9c9c9c', // 次要文本色
|
||||
comment: '#6272a4', // 注释色
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#ff79c6', // 关键字
|
||||
string: '#f1fa8c', // 字符串
|
||||
function: '#50fa7b', // 函数名
|
||||
number: '#bd93f9', // 数字
|
||||
operator: '#ff79c6', // 操作符
|
||||
variable: '#8fbcbb', // 变量
|
||||
type: '#8be9fd', // 类型
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#bd93f9', // 常量
|
||||
storage: '#ff79c6', // 存储类型
|
||||
parameter: '#8fbcbb', // 参数
|
||||
class: '#8be9fd', // 类名
|
||||
heading: '#ff79c6', // 标题
|
||||
invalid: '#d30102', // 无效内容
|
||||
regexp: '#f1fa8c', // 正则表达式
|
||||
|
||||
// 界面元素
|
||||
cursor: '#ffffff', // 光标
|
||||
selection: '#0865a9', // 选中背景
|
||||
selectionBlur: '#225377', // 失焦选中背景
|
||||
activeLine: '#ffffff0a', // 当前行高亮
|
||||
lineNumber: '#ffffff26', // 行号
|
||||
activeLineNumber: '#ffffff99', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#1e222a', // 边框色
|
||||
borderLight: '#ffffff19', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#8fbcbb', // 搜索匹配
|
||||
matchingBracket: '#ffffff19', // 匹配括号
|
||||
};
|
||||
|
||||
// 创建深色主题
|
||||
export function createDarkTheme(colors: ThemeColors = defaultDarkColors) {
|
||||
return createBaseTheme({...colors, dark: true});
|
||||
}
|
||||
|
||||
// 默认深色主题
|
||||
export const defaultDark = createDarkTheme(defaultDarkColors);
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
export const config: ThemeColors = {
|
||||
name: 'dracula',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#282A36',
|
||||
foreground: '#F8F8F2',
|
||||
selection: '#44475A',
|
||||
cursor: '#F8F8F2',
|
||||
backgroundSecondary: '#282A36',
|
||||
surface: '#282A36',
|
||||
dropdownBackground: '#282A36',
|
||||
dropdownBorder: '#191A21',
|
||||
activeLine: '#53576c22',
|
||||
lineNumber: '#6272A4',
|
||||
activeLineNumber: '#F8F8F2',
|
||||
matchingBracket: '#44475A',
|
||||
keyword: '#FF79C6',
|
||||
storage: '#FF79C6',
|
||||
variable: '#F8F8F2',
|
||||
parameter: '#F8F8F2',
|
||||
function: '#50FA7B',
|
||||
string: '#F1FA8C',
|
||||
constant: '#BD93F9',
|
||||
type: '#8BE9FD',
|
||||
class: '#8BE9FD',
|
||||
number: '#BD93F9',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#F8F8F2',
|
||||
foregroundSecondary: '#F8F8F2',
|
||||
comment: '#6272A4',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#FF79C6',
|
||||
string: '#F1FA8C',
|
||||
function: '#50FA7B',
|
||||
number: '#BD93F9',
|
||||
operator: '#FF79C6',
|
||||
variable: '#F8F8F2',
|
||||
type: '#8BE9FD',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#BD93F9',
|
||||
storage: '#FF79C6',
|
||||
parameter: '#F8F8F2',
|
||||
class: '#8BE9FD',
|
||||
heading: '#BD93F9',
|
||||
invalid: '#FF5555',
|
||||
regexp: '#F1FA8C',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#F8F8F2',
|
||||
selection: '#44475A',
|
||||
selectionBlur: '#44475A',
|
||||
activeLine: '#53576c22',
|
||||
lineNumber: '#6272A4',
|
||||
activeLineNumber: '#F8F8F2',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#191A21',
|
||||
borderLight: '#F8F8F219',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#50FA7B',
|
||||
matchingBracket: '#44475A',
|
||||
}
|
||||
|
||||
export const draculaTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const draculaHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const dracula: Extension = [
|
||||
draculaTheme,
|
||||
syntaxHighlighting(draculaHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Dracula 主题
|
||||
export const dracula: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView, lineNumbers} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'githubDark',
|
||||
export const config: ThemeColors = {
|
||||
name: 'github-dark',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#24292e',
|
||||
foreground: '#d1d5da',
|
||||
selection: '#3392FF44',
|
||||
cursor: '#c8e1ff',
|
||||
backgroundSecondary: '#24292e',
|
||||
surface: '#24292e',
|
||||
dropdownBackground: '#24292e',
|
||||
dropdownBorder: '#1b1f23',
|
||||
activeLine: '#4d566022',
|
||||
lineNumber: '#444d56',
|
||||
activeLineNumber: '#e1e4e8',
|
||||
matchingBracket: '#17E5E650',
|
||||
keyword: '#f97583',
|
||||
storage: '#f97583',
|
||||
variable: '#ffab70',
|
||||
parameter: '#e1e4e8',
|
||||
function: '#79b8ff',
|
||||
string: '#9ecbff',
|
||||
constant: '#79b8ff',
|
||||
type: '#79b8ff',
|
||||
class: '#b392f0',
|
||||
number: '#79b8ff',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#d1d5da',
|
||||
foregroundSecondary: '#d1d5da',
|
||||
comment: '#6a737d',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#f97583',
|
||||
string: '#9ecbff',
|
||||
function: '#79b8ff',
|
||||
number: '#79b8ff',
|
||||
operator: '#f97583',
|
||||
variable: '#ffab70',
|
||||
type: '#79b8ff',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#79b8ff',
|
||||
storage: '#f97583',
|
||||
parameter: '#e1e4e8',
|
||||
class: '#b392f0',
|
||||
heading: '#79b8ff',
|
||||
invalid: '#f97583',
|
||||
regexp: '#9ecbff',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#c8e1ff',
|
||||
selection: '#3392FF44',
|
||||
selectionBlur: '#3392FF44',
|
||||
activeLine: '#4d566022',
|
||||
lineNumber: '#444d56',
|
||||
activeLineNumber: '#e1e4e8',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#1b1f23',
|
||||
borderLight: '#d1d5da19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#79b8ff',
|
||||
matchingBracket: '#17E5E650',
|
||||
}
|
||||
|
||||
export const githubDarkTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const githubDarkHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const githubDark: Extension = [
|
||||
githubDarkTheme,
|
||||
syntaxHighlighting(githubDarkHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 GitHub Dark 主题
|
||||
export const githubDark: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'materialDark',
|
||||
export const config: ThemeColors = {
|
||||
name: 'material-dark',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#263238',
|
||||
foreground: '#EEFFFF',
|
||||
selection: '#80CBC420',
|
||||
cursor: '#FFCC00',
|
||||
backgroundSecondary: '#263238',
|
||||
surface: '#263238',
|
||||
dropdownBackground: '#263238',
|
||||
dropdownBorder: '#FFFFFF10',
|
||||
activeLine: '#4c616c22',
|
||||
lineNumber: '#37474F',
|
||||
activeLineNumber: '#607a86',
|
||||
matchingBracket: '#263238',
|
||||
keyword: '#C792EA',
|
||||
storage: '#C792EA',
|
||||
variable: '#EEFFFF',
|
||||
parameter: '#EEFFFF',
|
||||
function: '#82AAFF',
|
||||
string: '#C3E88D',
|
||||
constant: '#F78C6C',
|
||||
type: '#B2CCD6',
|
||||
class: '#FFCB6B',
|
||||
number: '#F78C6C',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#EEFFFF',
|
||||
foregroundSecondary: '#EEFFFF',
|
||||
comment: '#546E7A',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#C792EA',
|
||||
string: '#C3E88D',
|
||||
function: '#82AAFF',
|
||||
number: '#F78C6C',
|
||||
operator: '#C792EA',
|
||||
variable: '#EEFFFF',
|
||||
type: '#B2CCD6',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#F78C6C',
|
||||
storage: '#C792EA',
|
||||
parameter: '#EEFFFF',
|
||||
class: '#FFCB6B',
|
||||
heading: '#C3E88D',
|
||||
invalid: '#FF5370',
|
||||
regexp: '#89DDFF',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#FFCC00',
|
||||
selection: '#80CBC420',
|
||||
selectionBlur: '#80CBC420',
|
||||
activeLine: '#4c616c22',
|
||||
lineNumber: '#37474F',
|
||||
activeLineNumber: '#607a86',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#FFFFFF10',
|
||||
borderLight: '#EEFFFF19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#82AAFF',
|
||||
matchingBracket: '#263238',
|
||||
}
|
||||
|
||||
export const materialDarkTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const materialDarkHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const materialDark: Extension = [
|
||||
materialDarkTheme,
|
||||
syntaxHighlighting(materialDarkHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Material Dark 主题
|
||||
export const materialDark: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {EditorView} from "@codemirror/view"
|
||||
import {Extension} from "@codemirror/state"
|
||||
import {HighlightStyle, syntaxHighlighting} from "@codemirror/language"
|
||||
import {tags as t} from "@lezer/highlight"
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
// Using https://github.com/one-dark/vscode-one-dark-theme/ as reference for the colors
|
||||
|
||||
@@ -22,133 +21,56 @@ const chalky = "#e5c07b",
|
||||
selection = "#3E4451",
|
||||
cursor = "#528bff"
|
||||
|
||||
/// The colors used in the theme, as CSS color strings.
|
||||
export const color = {
|
||||
chalky,
|
||||
coral,
|
||||
cyan,
|
||||
invalid,
|
||||
ivory,
|
||||
stone,
|
||||
malibu,
|
||||
sage,
|
||||
whiskey,
|
||||
violet,
|
||||
darkBackground,
|
||||
highlightBackground,
|
||||
background,
|
||||
tooltipBackground,
|
||||
selection,
|
||||
cursor
|
||||
export const config: ThemeColors = {
|
||||
name: 'one-dark',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: background,
|
||||
backgroundSecondary: highlightBackground,
|
||||
surface: tooltipBackground,
|
||||
dropdownBackground: darkBackground,
|
||||
dropdownBorder: stone,
|
||||
|
||||
// 文本颜色
|
||||
foreground: ivory,
|
||||
foregroundSecondary: stone,
|
||||
comment: stone,
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: violet,
|
||||
string: sage,
|
||||
function: malibu,
|
||||
number: chalky,
|
||||
operator: cyan,
|
||||
variable: coral,
|
||||
type: chalky,
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: whiskey,
|
||||
storage: violet,
|
||||
parameter: coral,
|
||||
class: chalky,
|
||||
heading: coral,
|
||||
invalid: invalid,
|
||||
regexp: cyan,
|
||||
|
||||
// 界面元素
|
||||
cursor: cursor,
|
||||
selection: selection,
|
||||
selectionBlur: selection,
|
||||
activeLine: '#6699ff0b',
|
||||
lineNumber: stone,
|
||||
activeLineNumber: ivory,
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: darkBackground,
|
||||
borderLight: ivory + '19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: malibu,
|
||||
matchingBracket: '#bad0f847',
|
||||
}
|
||||
|
||||
/// The editor theme styles for One Dark.
|
||||
export const oneDarkTheme = EditorView.theme({
|
||||
"&": {
|
||||
color: ivory,
|
||||
backgroundColor: background
|
||||
},
|
||||
|
||||
".cm-content": {
|
||||
caretColor: cursor
|
||||
},
|
||||
|
||||
".cm-cursor, .cm-dropCursor": {borderLeftColor: cursor},
|
||||
"&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": {backgroundColor: selection},
|
||||
|
||||
".cm-panels": {backgroundColor: darkBackground, color: ivory},
|
||||
".cm-panels.cm-panels-top": {borderBottom: "2px solid black"},
|
||||
".cm-panels.cm-panels-bottom": {borderTop: "2px solid black"},
|
||||
|
||||
".cm-searchMatch": {
|
||||
backgroundColor: "#72a1ff59",
|
||||
outline: "1px solid #457dff"
|
||||
},
|
||||
".cm-searchMatch.cm-searchMatch-selected": {
|
||||
backgroundColor: "#6199ff2f"
|
||||
},
|
||||
|
||||
".cm-activeLine": {backgroundColor: "#6699ff0b"},
|
||||
".cm-selectionMatch": {backgroundColor: "#aafe661a"},
|
||||
|
||||
"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket": {
|
||||
backgroundColor: "#bad0f847"
|
||||
},
|
||||
|
||||
".cm-gutters": {
|
||||
backgroundColor: background,
|
||||
color: stone,
|
||||
border: "none"
|
||||
},
|
||||
|
||||
".cm-activeLineGutter": {
|
||||
backgroundColor: highlightBackground
|
||||
},
|
||||
|
||||
".cm-foldPlaceholder": {
|
||||
backgroundColor: "transparent",
|
||||
border: "none",
|
||||
color: "#ddd"
|
||||
},
|
||||
|
||||
".cm-tooltip": {
|
||||
border: "none",
|
||||
backgroundColor: tooltipBackground
|
||||
},
|
||||
".cm-tooltip .cm-tooltip-arrow:before": {
|
||||
borderTopColor: "transparent",
|
||||
borderBottomColor: "transparent"
|
||||
},
|
||||
".cm-tooltip .cm-tooltip-arrow:after": {
|
||||
borderTopColor: tooltipBackground,
|
||||
borderBottomColor: tooltipBackground
|
||||
},
|
||||
".cm-tooltip-autocomplete": {
|
||||
"& > ul > li[aria-selected]": {
|
||||
backgroundColor: highlightBackground,
|
||||
color: ivory
|
||||
}
|
||||
}
|
||||
}, {dark: true})
|
||||
|
||||
/// The highlighting style for code in the One Dark theme.
|
||||
export const oneDarkHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword,
|
||||
color: violet},
|
||||
{tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
|
||||
color: coral},
|
||||
{tag: [t.function(t.variableName), t.labelName],
|
||||
color: malibu},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)],
|
||||
color: whiskey},
|
||||
{tag: [t.definition(t.name), t.separator],
|
||||
color: ivory},
|
||||
{tag: [t.typeName, t.className, t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
|
||||
color: chalky},
|
||||
{tag: [t.operator, t.operatorKeyword, t.url, t.escape, t.regexp, t.link, t.special(t.string)],
|
||||
color: cyan},
|
||||
{tag: [t.meta, t.comment],
|
||||
color: stone},
|
||||
{tag: t.strong,
|
||||
fontWeight: "bold"},
|
||||
{tag: t.emphasis,
|
||||
fontStyle: "italic"},
|
||||
{tag: t.strikethrough,
|
||||
textDecoration: "line-through"},
|
||||
{tag: t.link,
|
||||
color: stone,
|
||||
textDecoration: "underline"},
|
||||
{tag: t.heading,
|
||||
fontWeight: "bold",
|
||||
color: coral},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)],
|
||||
color: whiskey },
|
||||
{tag: [t.processingInstruction, t.string, t.inserted],
|
||||
color: sage},
|
||||
{tag: t.invalid,
|
||||
color: invalid},
|
||||
])
|
||||
|
||||
/// Extension to enable the One Dark theme (both the editor theme and
|
||||
/// the highlight style).
|
||||
export const oneDark: Extension = [oneDarkTheme, syntaxHighlighting(oneDarkHighlightStyle)]
|
||||
// 使用通用主题工厂函数创建 One Dark 主题
|
||||
export const oneDark: Extension = createBaseTheme(config)
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'solarizedDark',
|
||||
export const config: ThemeColors = {
|
||||
name: 'solarized-dark',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#002B36',
|
||||
foreground: '#93A1A1',
|
||||
selection: '#274642',
|
||||
cursor: '#D30102',
|
||||
backgroundSecondary: '#002B36',
|
||||
surface: '#002B36',
|
||||
dropdownBackground: '#002B36',
|
||||
dropdownBorder: '#2AA19899',
|
||||
activeLine: '#005b7022',
|
||||
lineNumber: '#93A1A1',
|
||||
activeLineNumber: '#949494',
|
||||
matchingBracket: '#073642',
|
||||
keyword: '#859900',
|
||||
storage: '#93A1A1',
|
||||
variable: '#268BD2',
|
||||
parameter: '#268BD2',
|
||||
function: '#268BD2',
|
||||
string: '#2AA198',
|
||||
constant: '#CB4B16',
|
||||
type: '#CB4B16',
|
||||
class: '#CB4B16',
|
||||
number: '#D33682',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#93A1A1',
|
||||
foregroundSecondary: '#93A1A1',
|
||||
comment: '#586E75',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#859900',
|
||||
string: '#2AA198',
|
||||
function: '#268BD2',
|
||||
number: '#D33682',
|
||||
operator: '#859900',
|
||||
variable: '#268BD2',
|
||||
type: '#CB4B16',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#CB4B16',
|
||||
storage: '#93A1A1',
|
||||
parameter: '#268BD2',
|
||||
class: '#CB4B16',
|
||||
heading: '#268BD2',
|
||||
invalid: '#DC322F',
|
||||
regexp: '#DC322F',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#D30102',
|
||||
selection: '#274642',
|
||||
selectionBlur: '#274642',
|
||||
activeLine: '#005b7022',
|
||||
lineNumber: '#93A1A1',
|
||||
activeLineNumber: '#949494',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#073642',
|
||||
borderLight: '#93A1A119',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#2AA198',
|
||||
matchingBracket: '#073642',
|
||||
}
|
||||
|
||||
export const solarizedDarkTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const solarizedDarkHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const solarizedDark: Extension = [
|
||||
solarizedDarkTheme,
|
||||
syntaxHighlighting(solarizedDarkHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Solarized Dark 主题
|
||||
export const solarizedDark: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'tokyoNightStorm',
|
||||
export const config: ThemeColors = {
|
||||
name: 'tokyo-night-storm',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#24283b',
|
||||
foreground: '#7982a9',
|
||||
selection: '#6f7bb630',
|
||||
cursor: '#c0caf5',
|
||||
backgroundSecondary: '#24283b',
|
||||
surface: '#24283b',
|
||||
dropdownBackground: '#24283b',
|
||||
dropdownBorder: '#7982a9',
|
||||
activeLine: '#4d547722',
|
||||
lineNumber: '#3b4261',
|
||||
activeLineNumber: '#737aa2',
|
||||
matchingBracket: '#1f2335',
|
||||
keyword: '#bb9af7',
|
||||
storage: '#bb9af7',
|
||||
variable: '#c0caf5',
|
||||
parameter: '#c0caf5',
|
||||
function: '#7aa2f7',
|
||||
string: '#9ece6a',
|
||||
constant: '#bb9af7',
|
||||
type: '#2ac3de',
|
||||
class: '#c0caf5',
|
||||
number: '#ff9e64',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#7982a9',
|
||||
foregroundSecondary: '#7982a9',
|
||||
comment: '#565f89',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#bb9af7',
|
||||
string: '#9ece6a',
|
||||
function: '#7aa2f7',
|
||||
number: '#ff9e64',
|
||||
operator: '#bb9af7',
|
||||
variable: '#c0caf5',
|
||||
type: '#2ac3de',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#bb9af7',
|
||||
storage: '#bb9af7',
|
||||
parameter: '#c0caf5',
|
||||
class: '#c0caf5',
|
||||
heading: '#89ddff',
|
||||
invalid: '#ff5370',
|
||||
regexp: '#b4f9f8',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#c0caf5',
|
||||
selection: '#6f7bb630',
|
||||
selectionBlur: '#6f7bb630',
|
||||
activeLine: '#4d547722',
|
||||
lineNumber: '#3b4261',
|
||||
activeLineNumber: '#737aa2',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#1f2335',
|
||||
borderLight: '#7982a919',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#7aa2f7',
|
||||
matchingBracket: '#1f2335',
|
||||
}
|
||||
|
||||
export const tokyoNightStormTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const tokyoNightStormHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const tokyoNightStorm: Extension = [
|
||||
tokyoNightStormTheme,
|
||||
syntaxHighlighting(tokyoNightStormHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Tokyo Night Storm 主题
|
||||
export const tokyoNightStorm: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'tokyoNight',
|
||||
export const config: ThemeColors = {
|
||||
name: 'tokyo-night',
|
||||
dark: true,
|
||||
|
||||
// 基础色调
|
||||
background: '#1a1b26',
|
||||
foreground: '#787c99',
|
||||
selection: '#515c7e40',
|
||||
cursor: '#c0caf5',
|
||||
backgroundSecondary: '#1a1b26',
|
||||
surface: '#1a1b26',
|
||||
dropdownBackground: '#1a1b26',
|
||||
dropdownBorder: '#787c99',
|
||||
activeLine: '#43455c22',
|
||||
lineNumber: '#363b54',
|
||||
activeLineNumber: '#737aa2',
|
||||
matchingBracket: '#16161e',
|
||||
keyword: '#bb9af7',
|
||||
storage: '#bb9af7',
|
||||
variable: '#c0caf5',
|
||||
parameter: '#c0caf5',
|
||||
function: '#7aa2f7',
|
||||
string: '#9ece6a',
|
||||
constant: '#bb9af7',
|
||||
type: '#0db9d7',
|
||||
class: '#c0caf5',
|
||||
number: '#ff9e64',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#787c99',
|
||||
foregroundSecondary: '#787c99',
|
||||
comment: '#444b6a',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#bb9af7',
|
||||
string: '#9ece6a',
|
||||
function: '#7aa2f7',
|
||||
number: '#ff9e64',
|
||||
operator: '#bb9af7',
|
||||
variable: '#c0caf5',
|
||||
type: '#0db9d7',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#bb9af7',
|
||||
storage: '#bb9af7',
|
||||
parameter: '#c0caf5',
|
||||
class: '#c0caf5',
|
||||
heading: '#89ddff',
|
||||
invalid: '#ff5370',
|
||||
regexp: '#b4f9f8',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#c0caf5',
|
||||
selection: '#515c7e40',
|
||||
selectionBlur: '#515c7e40',
|
||||
activeLine: '#43455c22',
|
||||
lineNumber: '#363b54',
|
||||
activeLineNumber: '#737aa2',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#16161e',
|
||||
borderLight: '#787c9919',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#7aa2f7',
|
||||
matchingBracket: '#16161e',
|
||||
}
|
||||
|
||||
export const tokyoNightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const tokyoNightHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const tokyoNight: Extension = [
|
||||
tokyoNightTheme,
|
||||
syntaxHighlighting(tokyoNightHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Tokyo Night 主题
|
||||
export const tokyoNight: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
import {EditorView} from '@codemirror/view';
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language';
|
||||
import {tags} from '@lezer/highlight';
|
||||
|
||||
// 默认浅色主题颜色
|
||||
export const defaultLightColors = {
|
||||
// 基础色调
|
||||
background: '#ffffff', // 主背景色
|
||||
backgroundSecondary: '#f1faf1', // 次要背景色
|
||||
surface: '#f5f5f5', // 面板背景
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#444d56', // 主文本色
|
||||
foregroundSecondary: '#6a737d', // 次要文本色
|
||||
comment: '#6a737d', // 注释色
|
||||
|
||||
// 语法高亮色
|
||||
keyword: '#d73a49', // 关键字
|
||||
string: '#032f62', // 字符串
|
||||
function: '#005cc5', // 函数名
|
||||
number: '#005cc5', // 数字
|
||||
operator: '#d73a49', // 操作符
|
||||
variable: '#24292e', // 变量
|
||||
type: '#6f42c1', // 类型
|
||||
|
||||
// 界面元素
|
||||
cursor: '#000000', // 光标
|
||||
selection: '#77baff', // 选中背景
|
||||
selectionBlur: '#b2c2ca', // 失焦选中背景
|
||||
activeLine: '#0000000a', // 当前行高亮
|
||||
lineNumber: '#00000040', // 行号
|
||||
activeLineNumber: '#000000aa', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#dfdfdf', // 边框色
|
||||
borderLight: '#0000000c', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#005cc5', // 搜索匹配
|
||||
matchingBracket: '#00000019', // 匹配括号
|
||||
};
|
||||
|
||||
// 创建浅色主题
|
||||
export function createLightTheme(colors = defaultLightColors) {
|
||||
const lightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: colors.foreground,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 确保编辑器容器背景一致
|
||||
'.cm-editor': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 确保滚动区域背景一致
|
||||
'.cm-scroller': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 编辑器内容
|
||||
'.cm-content': {
|
||||
caretColor: colors.cursor,
|
||||
paddingTop: '4px',
|
||||
},
|
||||
|
||||
// 光标
|
||||
'.cm-cursor, .cm-dropCursor': {
|
||||
borderLeftColor: colors.cursor,
|
||||
borderLeftWidth: '2px',
|
||||
paddingTop: '4px',
|
||||
marginTop: '-2px',
|
||||
},
|
||||
|
||||
// 选择
|
||||
'.cm-selectionBackground': {
|
||||
backgroundColor: colors.selectionBlur,
|
||||
},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
'.cm-activeLine.code-empty-block-selected': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
|
||||
// 当前行高亮
|
||||
'.cm-activeLine': {
|
||||
backgroundColor: colors.activeLine
|
||||
},
|
||||
|
||||
// 行号区域
|
||||
'.cm-gutters': {
|
||||
backgroundColor: 'rgba(0,0,0, 0.04)',
|
||||
color: colors.lineNumber,
|
||||
border: 'none',
|
||||
borderRight: `1px solid ${colors.borderLight}`,
|
||||
padding: '0 2px 0 4px',
|
||||
userSelect: 'none',
|
||||
},
|
||||
'.cm-activeLineGutter': {
|
||||
backgroundColor: 'transparent',
|
||||
color: colors.activeLineNumber,
|
||||
},
|
||||
|
||||
// 折叠功能
|
||||
'.cm-foldGutter': {
|
||||
marginLeft: '0px',
|
||||
},
|
||||
'.cm-foldGutter .cm-gutterElement': {
|
||||
opacity: 0,
|
||||
transition: 'opacity 400ms',
|
||||
},
|
||||
'.cm-gutters:hover .cm-gutterElement': {
|
||||
opacity: 1,
|
||||
},
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: colors.comment,
|
||||
},
|
||||
|
||||
|
||||
// 搜索匹配
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: 'transparent',
|
||||
outline: `1px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: colors.searchMatch,
|
||||
color: colors.background,
|
||||
},
|
||||
'.cm-selectionMatch': {
|
||||
backgroundColor: '#e6f3ff',
|
||||
},
|
||||
|
||||
// 括号匹配
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: `0.5px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'&.cm-focused .cm-matchingBracket': {
|
||||
backgroundColor: colors.matchingBracket,
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: '0.5px solid #d73a49',
|
||||
},
|
||||
|
||||
// 编辑器焦点
|
||||
'&.cm-editor.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
|
||||
// 工具提示
|
||||
'.cm-tooltip': {
|
||||
border: 'none',
|
||||
backgroundColor: colors.surface,
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: colors.surface,
|
||||
borderBottomColor: colors.surface,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
backgroundColor: colors.activeLine,
|
||||
color: colors.foreground,
|
||||
},
|
||||
},
|
||||
|
||||
// 代码块层
|
||||
'.code-blocks-layer': {
|
||||
width: '100%',
|
||||
},
|
||||
'.code-blocks-layer .block-even, .code-blocks-layer .block-odd': {
|
||||
width: '100%',
|
||||
boxSizing: 'content-box',
|
||||
},
|
||||
'.code-blocks-layer .block-even': {
|
||||
background: colors.background,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-layer .block-even:first-child': {
|
||||
borderTop: 'none',
|
||||
},
|
||||
'.code-blocks-layer .block-odd': {
|
||||
background: colors.backgroundSecondary,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-math-result': {
|
||||
paddingLeft: "12px",
|
||||
position: "relative",
|
||||
},
|
||||
'.code-blocks-math-result .inner': {
|
||||
background: '#48b57e',
|
||||
color: '#fff',
|
||||
padding: '0px 4px',
|
||||
borderRadius: '2px',
|
||||
boxShadow: '0 0 3px rgba(0,0,0, 0.1)',
|
||||
cursor: 'pointer',
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
'.code-blocks-math-result-copied': {
|
||||
position: "absolute",
|
||||
top: "0px",
|
||||
left: "0px",
|
||||
marginLeft: "calc(100% + 10px)",
|
||||
width: "60px",
|
||||
transition: "opacity 500ms",
|
||||
transitionDelay: "1000ms",
|
||||
color: "rgba(0,0,0, 0.8)",
|
||||
},
|
||||
'.code-blocks-math-result-copied.fade-out': {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
// 代码块开始标记
|
||||
'.code-block-start': {
|
||||
height: '12px',
|
||||
},
|
||||
'.code-block-start.first': {
|
||||
height: '0px',
|
||||
},
|
||||
}, {dark: false});
|
||||
|
||||
// 语法高亮样式
|
||||
const lightHighlightStyle = HighlightStyle.define([
|
||||
{tag: tags.keyword, color: colors.keyword},
|
||||
{tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: colors.variable},
|
||||
{tag: [tags.variableName], color: colors.variable},
|
||||
{tag: [tags.function(tags.variableName)], color: colors.function},
|
||||
{tag: [tags.labelName], color: colors.operator},
|
||||
{tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: colors.keyword},
|
||||
{tag: [tags.definition(tags.name), tags.separator], color: colors.function},
|
||||
{tag: [tags.brace], color: colors.variable},
|
||||
{tag: [tags.annotation], color: '#d73a49'},
|
||||
{
|
||||
tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace],
|
||||
color: colors.number
|
||||
},
|
||||
{tag: [tags.typeName, tags.className], color: colors.type},
|
||||
{tag: [tags.operator, tags.operatorKeyword], color: colors.operator},
|
||||
{tag: [tags.tagName], color: colors.type},
|
||||
{tag: [tags.squareBracket], color: colors.keyword},
|
||||
{tag: [tags.angleBracket], color: colors.operator},
|
||||
{tag: [tags.attributeName], color: colors.variable},
|
||||
{tag: [tags.regexp], color: colors.string},
|
||||
{tag: [tags.quote], color: colors.comment},
|
||||
{tag: [tags.string], color: colors.string},
|
||||
{tag: tags.link, color: colors.function, textDecoration: 'underline'},
|
||||
{tag: [tags.url, tags.escape, tags.special(tags.string)], color: colors.string},
|
||||
{tag: [tags.meta], color: colors.comment},
|
||||
{tag: [tags.comment], color: colors.comment, fontStyle: 'italic'},
|
||||
{tag: tags.strong, fontWeight: 'bold'},
|
||||
{tag: tags.emphasis, fontStyle: 'italic'},
|
||||
{tag: tags.strikethrough, textDecoration: 'line-through'},
|
||||
{tag: tags.heading, fontWeight: 'bold', color: colors.keyword},
|
||||
{tag: [tags.heading1, tags.heading2], fontSize: '1.4em'},
|
||||
{tag: [tags.heading3, tags.heading4], fontSize: '1.2em'},
|
||||
{tag: [tags.heading5, tags.heading6], fontSize: '1.1em'},
|
||||
]);
|
||||
|
||||
return [
|
||||
lightTheme,
|
||||
syntaxHighlighting(lightHighlightStyle),
|
||||
];
|
||||
}
|
||||
|
||||
// 默认浅色主题
|
||||
export const light = createLightTheme(defaultLightColors);
|
||||
63
frontend/src/views/editor/theme/light/default-light.ts
Normal file
63
frontend/src/views/editor/theme/light/default-light.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {createBaseTheme} from '../base';
|
||||
import type {ThemeColors} from '../types';
|
||||
|
||||
// 默认浅色主题颜色
|
||||
export const defaultLightColors: ThemeColors = {
|
||||
// 主题信息
|
||||
name: 'default-light',
|
||||
dark: false,
|
||||
|
||||
// 基础色调
|
||||
background: '#ffffff', // 主背景色
|
||||
backgroundSecondary: '#f1faf1', // 次要背景色
|
||||
surface: '#f5f5f5', // 面板背景
|
||||
dropdownBackground: '#ffffff', // 下拉菜单背景
|
||||
dropdownBorder: '#e1e4e8', // 下拉菜单边框
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#444d56', // 主文本色
|
||||
foregroundSecondary: '#6a737d', // 次要文本色
|
||||
comment: '#6a737d', // 注释色
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#d73a49', // 关键字
|
||||
string: '#032f62', // 字符串
|
||||
function: '#005cc5', // 函数名
|
||||
number: '#005cc5', // 数字
|
||||
operator: '#d73a49', // 操作符
|
||||
variable: '#24292e', // 变量
|
||||
type: '#6f42c1', // 类型
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#005cc5', // 常量
|
||||
storage: '#d73a49', // 存储类型
|
||||
parameter: '#24292e', // 参数
|
||||
class: '#6f42c1', // 类名
|
||||
heading: '#d73a49', // 标题
|
||||
invalid: '#cb2431', // 无效内容
|
||||
regexp: '#032f62', // 正则表达式
|
||||
|
||||
// 界面元素
|
||||
cursor: '#000000', // 光标
|
||||
selection: '#77baff', // 选中背景
|
||||
selectionBlur: '#b2c2ca', // 失焦选中背景
|
||||
activeLine: '#0000000a', // 当前行高亮
|
||||
lineNumber: '#00000040', // 行号
|
||||
activeLineNumber: '#000000aa', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#dfdfdf', // 边框色
|
||||
borderLight: '#0000000c', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#005cc5', // 搜索匹配
|
||||
matchingBracket: '#00000019', // 匹配括号
|
||||
};
|
||||
|
||||
// 创建浅色主题
|
||||
export function createLightTheme(colors: ThemeColors = defaultLightColors) {
|
||||
return createBaseTheme({...colors, dark: false});
|
||||
}
|
||||
|
||||
// 默认浅色主题
|
||||
export const defaultLight = createLightTheme(defaultLightColors);
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'githubLight',
|
||||
export const config: ThemeColors = {
|
||||
name: 'github-light',
|
||||
dark: false,
|
||||
|
||||
// 基础色调
|
||||
background: '#fff',
|
||||
foreground: '#444d56',
|
||||
selection: '#0366d625',
|
||||
cursor: '#044289',
|
||||
backgroundSecondary: '#fff',
|
||||
surface: '#fff',
|
||||
dropdownBackground: '#fff',
|
||||
dropdownBorder: '#e1e4e8',
|
||||
activeLine: '#c6c6c622',
|
||||
lineNumber: '#1b1f234d',
|
||||
activeLineNumber: '#24292e',
|
||||
matchingBracket: '#34d05840',
|
||||
keyword: '#d73a49',
|
||||
storage: '#d73a49',
|
||||
variable: '#e36209',
|
||||
parameter: '#24292e',
|
||||
function: '#005cc5',
|
||||
string: '#032f62',
|
||||
constant: '#005cc5',
|
||||
type: '#005cc5',
|
||||
class: '#6f42c1',
|
||||
number: '#005cc5',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#444d56',
|
||||
foregroundSecondary: '#444d56',
|
||||
comment: '#6a737d',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#d73a49',
|
||||
string: '#032f62',
|
||||
function: '#005cc5',
|
||||
number: '#005cc5',
|
||||
operator: '#d73a49',
|
||||
variable: '#e36209',
|
||||
type: '#005cc5',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#005cc5',
|
||||
storage: '#d73a49',
|
||||
parameter: '#24292e',
|
||||
class: '#6f42c1',
|
||||
heading: '#005cc5',
|
||||
invalid: '#cb2431',
|
||||
regexp: '#032f62',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#044289',
|
||||
selection: '#0366d625',
|
||||
selectionBlur: '#0366d625',
|
||||
activeLine: '#c6c6c622',
|
||||
lineNumber: '#1b1f234d',
|
||||
activeLineNumber: '#24292e',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#e1e4e8',
|
||||
borderLight: '#444d5619',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#005cc5',
|
||||
matchingBracket: '#34d05840',
|
||||
}
|
||||
|
||||
export const githubLightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const githubLightHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const githubLight: Extension = [
|
||||
githubLightTheme,
|
||||
syntaxHighlighting(githubLightHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 GitHub Light 主题
|
||||
export const githubLight: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'materialLight',
|
||||
export const config: ThemeColors = {
|
||||
name: 'material-light',
|
||||
dark: false,
|
||||
|
||||
// 基础色调
|
||||
background: '#FAFAFA',
|
||||
foreground: '#90A4AE',
|
||||
selection: '#80CBC440',
|
||||
cursor: '#272727',
|
||||
backgroundSecondary: '#FAFAFA',
|
||||
surface: '#FAFAFA',
|
||||
dropdownBackground: '#FAFAFA',
|
||||
dropdownBorder: '#00000010',
|
||||
activeLine: '#c2c2c222',
|
||||
lineNumber: '#CFD8DC',
|
||||
activeLineNumber: '#7E939E',
|
||||
matchingBracket: '#FAFAFA',
|
||||
keyword: '#7C4DFF',
|
||||
storage: '#7C4DFF',
|
||||
variable: '#90A4AE',
|
||||
parameter: '#90A4AE',
|
||||
function: '#6182B8',
|
||||
string: '#91B859',
|
||||
constant: '#F76D47',
|
||||
type: '#8796B0',
|
||||
class: '#FFB62C',
|
||||
number: '#F76D47',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#90A4AE',
|
||||
foregroundSecondary: '#90A4AE',
|
||||
comment: '#90A4AE',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#7C4DFF',
|
||||
string: '#91B859',
|
||||
function: '#6182B8',
|
||||
number: '#F76D47',
|
||||
operator: '#7C4DFF',
|
||||
variable: '#90A4AE',
|
||||
type: '#8796B0',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#F76D47',
|
||||
storage: '#7C4DFF',
|
||||
parameter: '#90A4AE',
|
||||
class: '#FFB62C',
|
||||
heading: '#91B859',
|
||||
invalid: '#E53935',
|
||||
regexp: '#39ADB5',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#272727',
|
||||
selection: '#80CBC440',
|
||||
selectionBlur: '#80CBC440',
|
||||
activeLine: '#c2c2c222',
|
||||
lineNumber: '#CFD8DC',
|
||||
activeLineNumber: '#7E939E',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#00000010',
|
||||
borderLight: '#90A4AE19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#6182B8',
|
||||
matchingBracket: '#FAFAFA',
|
||||
}
|
||||
|
||||
export const materialLightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const materialLightHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const materialLight: Extension = [
|
||||
materialLightTheme,
|
||||
syntaxHighlighting(materialLightHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Material Light 主题
|
||||
export const materialLight: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'solarizedLight',
|
||||
export const config: ThemeColors = {
|
||||
name: 'solarized-light',
|
||||
dark: false,
|
||||
|
||||
// 基础色调
|
||||
background: '#FDF6E3',
|
||||
foreground: '#586E75',
|
||||
selection: '#EEE8D5',
|
||||
cursor: '#657B83',
|
||||
backgroundSecondary: '#FDF6E3',
|
||||
surface: '#FDF6E3',
|
||||
dropdownBackground: '#FDF6E3',
|
||||
dropdownBorder: '#D3AF86',
|
||||
activeLine: '#d5bd5c22',
|
||||
lineNumber: '#586E75',
|
||||
activeLineNumber: '#567983',
|
||||
matchingBracket: '#EEE8D5',
|
||||
keyword: '#859900',
|
||||
storage: '#586E75',
|
||||
variable: '#268BD2',
|
||||
parameter: '#268BD2',
|
||||
function: '#268BD2',
|
||||
string: '#2AA198',
|
||||
constant: '#CB4B16',
|
||||
type: '#CB4B16',
|
||||
class: '#CB4B16',
|
||||
number: '#D33682',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#586E75',
|
||||
foregroundSecondary: '#586E75',
|
||||
comment: '#93A1A1',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#859900',
|
||||
string: '#2AA198',
|
||||
function: '#268BD2',
|
||||
number: '#D33682',
|
||||
operator: '#859900',
|
||||
variable: '#268BD2',
|
||||
type: '#CB4B16',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#CB4B16',
|
||||
storage: '#586E75',
|
||||
parameter: '#268BD2',
|
||||
class: '#CB4B16',
|
||||
heading: '#268BD2',
|
||||
invalid: '#DC322F',
|
||||
regexp: '#DC322F',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#657B83',
|
||||
selection: '#EEE8D5',
|
||||
selectionBlur: '#EEE8D5',
|
||||
activeLine: '#d5bd5c22',
|
||||
lineNumber: '#586E75',
|
||||
activeLineNumber: '#567983',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#EEE8D5',
|
||||
borderLight: '#586E7519',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#268BD2',
|
||||
matchingBracket: '#EEE8D5',
|
||||
}
|
||||
|
||||
export const solarizedLightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const solarizedLightHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const solarizedLight: Extension = [
|
||||
solarizedLightTheme,
|
||||
syntaxHighlighting(solarizedLightHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Solarized Light 主题
|
||||
export const solarizedLight: Extension = createBaseTheme(config)
|
||||
|
||||
@@ -1,128 +1,57 @@
|
||||
import {EditorView} from '@codemirror/view'
|
||||
import {Extension} from '@codemirror/state'
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language'
|
||||
import {tags as t} from '@lezer/highlight'
|
||||
import {createBaseTheme} from '../base'
|
||||
import type {ThemeColors} from '../types'
|
||||
|
||||
export const config = {
|
||||
name: 'tokyoNightDay',
|
||||
export const config: ThemeColors = {
|
||||
name: 'tokyo-night-day',
|
||||
dark: false,
|
||||
|
||||
// 基础色调
|
||||
background: '#e1e2e7',
|
||||
foreground: '#6a6f8e',
|
||||
selection: '#8591b840',
|
||||
cursor: '#3760bf',
|
||||
backgroundSecondary: '#e1e2e7',
|
||||
surface: '#e1e2e7',
|
||||
dropdownBackground: '#e1e2e7',
|
||||
dropdownBorder: '#6a6f8e',
|
||||
activeLine: '#a7aaba22',
|
||||
lineNumber: '#b3b6cd',
|
||||
activeLineNumber: '#68709a',
|
||||
matchingBracket: '#e9e9ec',
|
||||
keyword: '#9854f1',
|
||||
storage: '#9854f1',
|
||||
variable: '#3760bf',
|
||||
parameter: '#3760bf',
|
||||
function: '#2e7de9',
|
||||
string: '#587539',
|
||||
constant: '#9854f1',
|
||||
type: '#07879d',
|
||||
class: '#3760bf',
|
||||
number: '#b15c00',
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#6a6f8e',
|
||||
foregroundSecondary: '#6a6f8e',
|
||||
comment: '#9da3c2',
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
keyword: '#9854f1',
|
||||
string: '#587539',
|
||||
function: '#2e7de9',
|
||||
number: '#b15c00',
|
||||
operator: '#9854f1',
|
||||
variable: '#3760bf',
|
||||
type: '#07879d',
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: '#9854f1',
|
||||
storage: '#9854f1',
|
||||
parameter: '#3760bf',
|
||||
class: '#3760bf',
|
||||
heading: '#006a83',
|
||||
invalid: '#ff3e64',
|
||||
regexp: '#2e5857',
|
||||
|
||||
// 界面元素
|
||||
cursor: '#3760bf',
|
||||
selection: '#8591b840',
|
||||
selectionBlur: '#8591b840',
|
||||
activeLine: '#a7aaba22',
|
||||
lineNumber: '#b3b6cd',
|
||||
activeLineNumber: '#68709a',
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#e9e9ec',
|
||||
borderLight: '#6a6f8e19',
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#2e7de9',
|
||||
matchingBracket: '#e9e9ec',
|
||||
}
|
||||
|
||||
export const tokyoNightDayTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: config.foreground,
|
||||
backgroundColor: config.background,
|
||||
},
|
||||
|
||||
'.cm-content': {caretColor: config.cursor},
|
||||
|
||||
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
|
||||
|
||||
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
|
||||
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
|
||||
'.cm-panels.cm-panels-bottom': {borderTop: '2px solid black'},
|
||||
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: config.dropdownBackground,
|
||||
outline: `1px solid ${config.dropdownBorder}`
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: config.selection
|
||||
},
|
||||
|
||||
'.cm-activeLine': {backgroundColor: config.activeLine},
|
||||
'.cm-selectionMatch': {backgroundColor: config.selection},
|
||||
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
backgroundColor: config.matchingBracket,
|
||||
outline: 'none'
|
||||
},
|
||||
|
||||
'.cm-gutters': {
|
||||
backgroundColor: config.background,
|
||||
color: config.foreground,
|
||||
border: 'none'
|
||||
},
|
||||
'.cm-activeLineGutter': {backgroundColor: config.background},
|
||||
|
||||
'.cm-lineNumbers .cm-gutterElement': {color: config.lineNumber},
|
||||
'.cm-lineNumbers .cm-activeLineGutter': {color: config.activeLineNumber},
|
||||
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: config.foreground
|
||||
},
|
||||
'.cm-tooltip': {
|
||||
border: `1px solid ${config.dropdownBorder}`,
|
||||
backgroundColor: config.dropdownBackground,
|
||||
color: config.foreground,
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent'
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: config.foreground,
|
||||
borderBottomColor: config.foreground,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
background: config.selection,
|
||||
color: config.foreground,
|
||||
}
|
||||
}
|
||||
}, {dark: config.dark})
|
||||
|
||||
export const tokyoNightDayHighlightStyle = HighlightStyle.define([
|
||||
{tag: t.keyword, color: config.keyword},
|
||||
{tag: [t.name, t.deleted, t.character, t.macroName], color: config.variable},
|
||||
{tag: [t.propertyName], color: config.function},
|
||||
{tag: [t.processingInstruction, t.string, t.inserted, t.special(t.string)], color: config.string},
|
||||
{tag: [t.function(t.variableName), t.labelName], color: config.function},
|
||||
{tag: [t.color, t.constant(t.name), t.standard(t.name)], color: config.constant},
|
||||
{tag: [t.definition(t.name), t.separator], color: config.variable},
|
||||
{tag: [t.className], color: config.class},
|
||||
{tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], color: config.number},
|
||||
{tag: [t.typeName], color: config.type, fontStyle: config.type},
|
||||
{tag: [t.operator, t.operatorKeyword], color: config.keyword},
|
||||
{tag: [t.url, t.escape, t.regexp, t.link], color: config.regexp},
|
||||
{tag: [t.meta, t.comment], color: config.comment},
|
||||
{tag: t.strong, fontWeight: 'bold'},
|
||||
{tag: t.emphasis, fontStyle: 'italic'},
|
||||
{tag: t.link, textDecoration: 'underline'},
|
||||
{tag: t.heading, fontWeight: 'bold', color: config.heading},
|
||||
{tag: [t.atom, t.bool, t.special(t.variableName)], color: config.variable},
|
||||
{tag: t.invalid, color: config.invalid},
|
||||
{tag: t.strikethrough, textDecoration: 'line-through'},
|
||||
])
|
||||
|
||||
export const tokyoNightDay: Extension = [
|
||||
tokyoNightDayTheme,
|
||||
syntaxHighlighting(tokyoNightDayHighlightStyle),
|
||||
]
|
||||
// 使用通用主题工厂函数创建 Tokyo Night Day 主题
|
||||
export const tokyoNightDay: Extension = createBaseTheme(config)
|
||||
|
||||
59
frontend/src/views/editor/theme/registry.ts
Normal file
59
frontend/src/views/editor/theme/registry.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Extension } from '@codemirror/state';
|
||||
import type { ThemeColors } from './types';
|
||||
import { createBaseTheme } from './base';
|
||||
|
||||
// 深色主题导入
|
||||
import { config as draculaConfig } from './dark/dracula';
|
||||
import { config as auraConfig } from './dark/aura';
|
||||
import { config as githubDarkConfig } from './dark/github-dark';
|
||||
import { config as materialDarkConfig } from './dark/material-dark';
|
||||
import { config as oneDarkConfig } from './dark/one-dark';
|
||||
import { config as solarizedDarkConfig } from './dark/solarized-dark';
|
||||
import { config as tokyoNightConfig } from './dark/tokyo-night';
|
||||
import { config as tokyoNightStormConfig } from './dark/tokyo-night-storm';
|
||||
|
||||
// 浅色主题导入
|
||||
import { config as githubLightConfig } from './light/github-light';
|
||||
import { config as materialLightConfig } from './light/material-light';
|
||||
import { config as solarizedLightConfig } from './light/solarized-light';
|
||||
import { config as tokyoNightDayConfig } from './light/tokyo-night-day';
|
||||
|
||||
/**
|
||||
* 主题配置映射表
|
||||
* key: 主题名称(与数据库中的 name 字段一致)
|
||||
* value: 主题颜色配置
|
||||
*/
|
||||
const themeConfigMap: Record<string, ThemeColors> = {
|
||||
// 深色主题
|
||||
'dracula': draculaConfig,
|
||||
'aura': auraConfig,
|
||||
'github-dark': githubDarkConfig,
|
||||
'material-dark': materialDarkConfig,
|
||||
'one-dark': oneDarkConfig,
|
||||
'solarized-dark': solarizedDarkConfig,
|
||||
'tokyo-night': tokyoNightConfig,
|
||||
'tokyo-night-storm': tokyoNightStormConfig,
|
||||
|
||||
// 浅色主题
|
||||
'github-light': githubLightConfig,
|
||||
'material-light': materialLightConfig,
|
||||
'solarized-light': solarizedLightConfig,
|
||||
'tokyo-night-day': tokyoNightDayConfig,
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据主题名称获取主题配置
|
||||
*/
|
||||
export function getThemeConfig(themeName: string): ThemeColors | null {
|
||||
return themeConfigMap[themeName] || null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据自定义颜色配置创建主题
|
||||
*/
|
||||
export function createThemeByColors(colors: ThemeColors): Extension {
|
||||
return createBaseTheme(colors);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +1,52 @@
|
||||
export interface ThemeColors {
|
||||
// 主题基本信息
|
||||
name?: string; // 主题名称
|
||||
dark?: boolean; // 是否为深色主题标识
|
||||
name: string; // 主题名称
|
||||
dark: boolean; // 是否为深色主题标识
|
||||
|
||||
// 基础色调
|
||||
background: string; // 主背景色
|
||||
backgroundSecondary?: string; // 次要背景色
|
||||
surface?: string; // 面板背景
|
||||
dropdownBackground?: string; // 下拉菜单背景
|
||||
dropdownBorder?: string; // 下拉菜单边框
|
||||
backgroundSecondary: string; // 次要背景色(用于代码块交替背景)
|
||||
surface: string; // 面板背景
|
||||
dropdownBackground: string; // 下拉菜单背景
|
||||
dropdownBorder: string; // 下拉菜单边框
|
||||
|
||||
// 文本颜色
|
||||
foreground: string; // 主文本色
|
||||
foregroundSecondary?: string; // 次要文本色
|
||||
foregroundSecondary: string; // 次要文本色
|
||||
comment: string; // 注释色
|
||||
|
||||
// 语法高亮色
|
||||
// 语法高亮色 - 核心
|
||||
keyword: string; // 关键字
|
||||
string: string; // 字符串
|
||||
function: string; // 函数名
|
||||
number: string; // 数字
|
||||
operator?: string; // 操作符
|
||||
operator: string; // 操作符
|
||||
variable: string; // 变量
|
||||
type: string; // 类型
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
constant: string; // 常量
|
||||
storage?: string; // 存储类型
|
||||
parameter?: string; // 参数
|
||||
class?: string; // 类名
|
||||
heading?: string; // 标题
|
||||
invalid?: string; // 无效内容
|
||||
regexp?: string; // 正则表达式
|
||||
storage: string; // 存储类型(如 static, const)
|
||||
parameter: string; // 参数
|
||||
class: string; // 类名
|
||||
heading: string; // 标题(Markdown等)
|
||||
invalid: string; // 无效内容/错误
|
||||
regexp: string; // 正则表达式
|
||||
|
||||
// 界面元素
|
||||
cursor: string; // 光标
|
||||
selection: string; // 选中背景
|
||||
selectionBlur?: string; // 失焦选中背景
|
||||
selectionBlur: string; // 失焦选中背景
|
||||
activeLine: string; // 当前行高亮
|
||||
lineNumber: string; // 行号
|
||||
activeLineNumber: string; // 活动行号颜色
|
||||
|
||||
// 边框和分割线
|
||||
borderColor?: string; // 边框色
|
||||
borderLight?: string; // 浅色边框
|
||||
borderColor: string; // 边框色
|
||||
borderLight: string; // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch?: string; // 搜索匹配
|
||||
matchingBracket?: string; // 匹配括号
|
||||
searchMatch: string; // 搜索匹配
|
||||
matchingBracket: string; // 匹配括号
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,10 @@ import { computed, watch, onMounted, ref } from 'vue';
|
||||
import SettingSection from '../components/SettingSection.vue';
|
||||
import SettingItem from '../components/SettingItem.vue';
|
||||
import { SystemThemeType, LanguageType } from '@/../bindings/voidraft/internal/models/models';
|
||||
import { defaultDarkColors } from '@/views/editor/theme/dark';
|
||||
import { defaultLightColors } from '@/views/editor/theme/light';
|
||||
import { createDebounce } from '@/common/utils/debounce';
|
||||
import { createTimerManager } from '@/common/utils/timerUtils';
|
||||
import PickColors from 'vue-pick-colors';
|
||||
import type { ThemeColors } from '@/views/editor/theme/types';
|
||||
|
||||
const { t } = useI18n();
|
||||
const configStore = useConfigStore();
|
||||
@@ -24,14 +23,12 @@ const { debouncedFn: debouncedUpdateColor } = createDebounce(
|
||||
|
||||
const { debouncedFn: debouncedResetTheme } = createDebounce(
|
||||
async () => {
|
||||
const themeType = activeThemeType.value;
|
||||
const success = await themeStore.resetThemeColors(themeType);
|
||||
const isDark = isDarkMode.value;
|
||||
const success = await themeStore.resetCurrentTheme(isDark);
|
||||
|
||||
if (success) {
|
||||
tempColors.value = {
|
||||
darkTheme: { ...themeStore.themeColors.darkTheme },
|
||||
lightTheme: { ...themeStore.themeColors.lightTheme }
|
||||
};
|
||||
// 重新加载临时颜色
|
||||
syncTempColors();
|
||||
hasUnsavedChanges.value = false;
|
||||
}
|
||||
},
|
||||
@@ -41,11 +38,8 @@ const { debouncedFn: debouncedResetTheme } = createDebounce(
|
||||
// 创建定时器管理器
|
||||
const resetTimer = createTimerManager();
|
||||
|
||||
// 添加临时颜色状态
|
||||
const tempColors = ref({
|
||||
darkTheme: { ...defaultDarkColors },
|
||||
lightTheme: { ...defaultLightColors }
|
||||
});
|
||||
// 临时颜色状态(用于编辑)
|
||||
const tempColors = ref<ThemeColors | null>(null);
|
||||
|
||||
// 标记是否有未保存的更改
|
||||
const hasUnsavedChanges = ref(false);
|
||||
@@ -55,82 +49,73 @@ const resetButtonState = ref({
|
||||
confirming: false
|
||||
});
|
||||
|
||||
// 当前激活的主题类型
|
||||
// 当前激活的主题类型(深色/浅色)
|
||||
const isDarkMode = computed(() =>
|
||||
themeStore.currentTheme === SystemThemeType.SystemThemeDark ||
|
||||
(themeStore.currentTheme === SystemThemeType.SystemThemeAuto &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
);
|
||||
|
||||
const activeThemeType = computed(() => isDarkMode.value ? 'darkTheme' : 'lightTheme');
|
||||
// 当前可用的预设主题列表
|
||||
const availableThemes = computed(() =>
|
||||
isDarkMode.value ? themeStore.darkThemes : themeStore.lightThemes
|
||||
);
|
||||
|
||||
// 当前主题的颜色配置
|
||||
const currentColors = computed(() => {
|
||||
const themeType = activeThemeType.value;
|
||||
return tempColors.value[themeType] ||
|
||||
(themeType === 'darkTheme' ? defaultDarkColors : defaultLightColors);
|
||||
// 当前选中的主题ID
|
||||
const currentThemeId = computed({
|
||||
get: () => isDarkMode.value ? themeStore.currentThemeIds.dark : themeStore.currentThemeIds.light,
|
||||
set: async (themeId: number) => {
|
||||
await themeStore.switchToTheme(themeId);
|
||||
syncTempColors();
|
||||
hasUnsavedChanges.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 获取当前主题模式
|
||||
// 当前主题的颜色配置
|
||||
const currentColors = computed(() => tempColors.value || ({} as ThemeColors));
|
||||
|
||||
// 获取当前主题模式(用于颜色选择器)
|
||||
const currentThemeMode = computed(() => isDarkMode.value ? 'dark' : 'light');
|
||||
|
||||
// 监听主题颜色变更,
|
||||
// 同步临时颜色从 store
|
||||
const syncTempColors = () => {
|
||||
const colors = isDarkMode.value ? themeStore.currentColors.dark : themeStore.currentColors.light;
|
||||
if (colors) {
|
||||
tempColors.value = { ...colors };
|
||||
}
|
||||
};
|
||||
|
||||
// 监听主题切换,同步临时颜色
|
||||
watch(
|
||||
() => themeStore.themeColors,
|
||||
(newValue) => {
|
||||
[() => themeStore.currentColors.dark, () => themeStore.currentColors.light, isDarkMode],
|
||||
() => {
|
||||
if (!hasUnsavedChanges.value) {
|
||||
tempColors.value.darkTheme = { ...newValue.darkTheme };
|
||||
tempColors.value.lightTheme = { ...newValue.lightTheme };
|
||||
syncTempColors();
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
tempColors.value = {
|
||||
darkTheme: { ...themeStore.themeColors.darkTheme },
|
||||
lightTheme: { ...themeStore.themeColors.lightTheme }
|
||||
};
|
||||
syncTempColors();
|
||||
});
|
||||
|
||||
// 颜色配置
|
||||
const colorConfig = [
|
||||
{
|
||||
key: 'basic',
|
||||
colors: ['background', 'backgroundSecondary', 'surface']
|
||||
},
|
||||
{
|
||||
key: 'text',
|
||||
colors: ['foreground', 'foregroundSecondary', 'comment']
|
||||
},
|
||||
{
|
||||
key: 'syntax',
|
||||
colors: ['keyword', 'string', 'function', 'number', 'operator', 'variable', 'type']
|
||||
},
|
||||
{
|
||||
key: 'interface',
|
||||
colors: ['cursor', 'selection', 'selectionBlur', 'activeLine', 'lineNumber', 'activeLineNumber']
|
||||
},
|
||||
{
|
||||
key: 'border',
|
||||
colors: ['borderColor', 'borderLight']
|
||||
},
|
||||
{
|
||||
key: 'search',
|
||||
colors: ['searchMatch', 'matchingBracket']
|
||||
}
|
||||
];
|
||||
// 从 ThemeColors 接口自动提取所有颜色字段
|
||||
const colorKeys = computed(() => {
|
||||
if (!tempColors.value) return [];
|
||||
|
||||
// 颜色配置分组
|
||||
const colorGroups = computed(() =>
|
||||
colorConfig.map(group => ({
|
||||
key: group.key,
|
||||
title: t(`settings.themeColors.${group.key}`),
|
||||
colors: group.colors.map(colorKey => ({
|
||||
// 获取所有字段,排除 name 和 dark(这两个是元数据)
|
||||
return Object.keys(tempColors.value).filter(key =>
|
||||
key !== 'name' && key !== 'dark'
|
||||
);
|
||||
});
|
||||
|
||||
// 颜色配置列表
|
||||
const colorList = computed(() =>
|
||||
colorKeys.value.map(colorKey => ({
|
||||
key: colorKey,
|
||||
label: t(`settings.themeColors.${colorKey}`)
|
||||
}))
|
||||
}))
|
||||
);
|
||||
|
||||
// 处理重置按钮点击
|
||||
@@ -152,15 +137,12 @@ const handleResetClick = () => {
|
||||
|
||||
// 更新本地颜色配置
|
||||
const updateLocalColor = (colorKey: string, value: string) => {
|
||||
const themeType = activeThemeType.value;
|
||||
if (!tempColors.value) return;
|
||||
|
||||
// 更新临时颜色
|
||||
tempColors.value = {
|
||||
...tempColors.value,
|
||||
[themeType]: {
|
||||
...tempColors.value[themeType],
|
||||
[colorKey]: value
|
||||
}
|
||||
};
|
||||
|
||||
hasUnsavedChanges.value = true;
|
||||
@@ -169,17 +151,15 @@ const updateLocalColor = (colorKey: string, value: string) => {
|
||||
// 应用颜色更改到系统
|
||||
const applyChanges = async () => {
|
||||
try {
|
||||
// 获取当前主题的自定义颜色
|
||||
const customTheme = {
|
||||
darkTheme: tempColors.value.darkTheme,
|
||||
lightTheme: tempColors.value.lightTheme
|
||||
};
|
||||
if (!tempColors.value) return;
|
||||
|
||||
// 更新themeStore中的颜色
|
||||
themeStore.updateThemeColors(customTheme.darkTheme, customTheme.lightTheme);
|
||||
const isDark = isDarkMode.value;
|
||||
|
||||
// 保存到配置
|
||||
await themeStore.saveThemeColors();
|
||||
// 更新 store 中的颜色
|
||||
themeStore.updateCurrentColors(tempColors.value, isDark);
|
||||
|
||||
// 保存到数据库
|
||||
await themeStore.saveCurrentTheme(isDark);
|
||||
|
||||
// 刷新编辑器主题
|
||||
themeStore.refreshEditorTheme();
|
||||
@@ -193,11 +173,8 @@ const applyChanges = async () => {
|
||||
|
||||
// 取消颜色更改
|
||||
const cancelChanges = () => {
|
||||
// 恢复到themeStore中的颜色
|
||||
tempColors.value = {
|
||||
darkTheme: { ...themeStore.themeColors.darkTheme },
|
||||
lightTheme: { ...themeStore.themeColors.lightTheme }
|
||||
};
|
||||
// 恢复到 store 中的颜色
|
||||
syncTempColors();
|
||||
|
||||
// 清除未保存标记
|
||||
hasUnsavedChanges.value = false;
|
||||
@@ -266,6 +243,15 @@ const handlePickerClose = () => {
|
||||
</option>
|
||||
</select>
|
||||
</SettingItem>
|
||||
|
||||
<!-- 预设主题选择 -->
|
||||
<SettingItem :title="t('settings.presetTheme')">
|
||||
<select class="select-input" v-model="currentThemeId" :disabled="hasUnsavedChanges">
|
||||
<option v-for="theme in availableThemes" :key="theme.id" :value="theme.id">
|
||||
{{ theme.name }}
|
||||
</option>
|
||||
</select>
|
||||
</SettingItem>
|
||||
</SettingSection>
|
||||
|
||||
<!-- 自定义主题颜色配置 -->
|
||||
@@ -290,12 +276,10 @@ const handlePickerClose = () => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="color-groups">
|
||||
<div v-for="group in colorGroups" :key="group.key" class="color-group">
|
||||
<h4 class="group-title">{{ group.title }}</h4>
|
||||
<div class="color-items">
|
||||
<!-- 颜色列表 -->
|
||||
<div class="color-list">
|
||||
<SettingItem
|
||||
v-for="color in group.colors"
|
||||
v-for="color in colorList"
|
||||
:key="color.key"
|
||||
:title="color.label"
|
||||
class="color-setting-item"
|
||||
@@ -328,8 +312,6 @@ const handlePickerClose = () => {
|
||||
</div>
|
||||
</SettingItem>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SettingSection>
|
||||
</div>
|
||||
</template>
|
||||
@@ -430,27 +412,11 @@ const handlePickerClose = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.color-groups {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.color-group {
|
||||
.group-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--settings-text);
|
||||
margin: 0 0 12px 0;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid var(--settings-input-border);
|
||||
}
|
||||
|
||||
.color-items {
|
||||
.color-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.color-setting-item {
|
||||
|
||||
6
go.mod
6
go.mod
@@ -10,11 +10,11 @@ require (
|
||||
github.com/knadh/koanf/providers/structs v1.0.0
|
||||
github.com/knadh/koanf/v2 v2.3.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.34
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.36
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/sys v0.37.0
|
||||
golang.org/x/text v0.30.0
|
||||
modernc.org/sqlite v1.39.0
|
||||
modernc.org/sqlite v1.39.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -72,7 +72,7 @@ require (
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.21 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.22 // indirect
|
||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||
github.com/xanzy/go-gitlab v0.115.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
|
||||
12
go.sum
12
go.sum
@@ -162,12 +162,12 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
|
||||
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/wailsapp/go-webview2 v1.0.21 h1:k3dtoZU4KCoN/AEIbWiPln3P2661GtA2oEgA2Pb+maA=
|
||||
github.com/wailsapp/go-webview2 v1.0.21/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6NZijQ58=
|
||||
github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.34 h1:t6NwHOLJzXuESb3YSXarSd1C/U1h2CpXF+BLr0ekj2g=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.34/go.mod h1:UZpnhYuju4saspCJrIHAvC0H5XjtKnqd26FRxJLrQ0M=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.36 h1:GQ8vSrFgafITwMd/p4k+WBjG9K/anma9Pk2eJ/5CLsI=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.36/go.mod h1:7i8tSuA74q97zZ5qEJlcVZdnO+IR7LT2KU8UpzYMPsw=
|
||||
github.com/xanzy/go-gitlab v0.115.0 h1:6DmtItNcVe+At/liXSgfE/DZNZrGfalQmBRmOcJjOn8=
|
||||
github.com/xanzy/go-gitlab v0.115.0/go.mod h1:5XCDtM7AM6WMKmfDdOiEpyRWUqui2iS9ILfvCZ2gJ5M=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
@@ -256,8 +256,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.39.0 h1:6bwu9Ooim0yVYA7IZn9demiQk/Ejp0BtTjBWFLymSeY=
|
||||
modernc.org/sqlite v1.39.0/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
|
||||
modernc.org/sqlite v1.39.1 h1:H+/wGFzuSCIEVCvXYVHX5RQglwhMOvtHSv+VtidL2r4=
|
||||
modernc.org/sqlite v1.39.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
|
||||
@@ -14,17 +14,25 @@ const (
|
||||
ThemeTypeLight ThemeType = "light"
|
||||
)
|
||||
|
||||
// ThemeColorConfig 主题颜色配置
|
||||
// ThemeColorConfig 主题颜色配置(与前端 ThemeColors 接口保持一致)
|
||||
type ThemeColorConfig struct {
|
||||
// 主题基本信息
|
||||
Name string `json:"name"` // 主题名称
|
||||
Dark bool `json:"dark"` // 是否为深色主题
|
||||
|
||||
// 基础色调
|
||||
Background string `json:"background"` // 主背景色
|
||||
BackgroundSecondary string `json:"backgroundSecondary"` // 次要背景色
|
||||
BackgroundSecondary string `json:"backgroundSecondary"` // 次要背景色(用于代码块交替背景)
|
||||
Surface string `json:"surface"` // 面板背景
|
||||
DropdownBackground string `json:"dropdownBackground"` // 下拉菜单背景
|
||||
DropdownBorder string `json:"dropdownBorder"` // 下拉菜单边框
|
||||
|
||||
// 文本颜色
|
||||
Foreground string `json:"foreground"` // 主文本色
|
||||
ForegroundSecondary string `json:"foregroundSecondary"` // 次要文本色
|
||||
|
||||
// 语法高亮
|
||||
Comment string `json:"comment"` // 注释色
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
Keyword string `json:"keyword"` // 关键字
|
||||
String string `json:"string"` // 字符串
|
||||
Function string `json:"function"` // 函数名
|
||||
@@ -33,34 +41,32 @@ type ThemeColorConfig struct {
|
||||
Variable string `json:"variable"` // 变量
|
||||
Type string `json:"type"` // 类型
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
Constant string `json:"constant"` // 常量
|
||||
Storage string `json:"storage"` // 存储类型(如 static, const)
|
||||
Parameter string `json:"parameter"` // 参数
|
||||
Class string `json:"class"` // 类名
|
||||
Heading string `json:"heading"` // 标题(Markdown等)
|
||||
Invalid string `json:"invalid"` // 无效内容/错误
|
||||
Regexp string `json:"regexp"` // 正则表达式
|
||||
|
||||
// 界面元素
|
||||
Cursor string `json:"cursor"` // 光标
|
||||
Selection string `json:"selection"` // 选中背景
|
||||
SelectionBlur string `json:"selectionBlur"` // 失焦选中背景
|
||||
ActiveLine string `json:"activeLine"` // 当前行高亮
|
||||
LineNumber string `json:"lineNumber"` // 行号
|
||||
ActiveLineNumber string `json:"activeLineNumber"` // 活动行号
|
||||
ActiveLineNumber string `json:"activeLineNumber"` // 活动行号颜色
|
||||
|
||||
// 边框分割线
|
||||
// 边框和分割线
|
||||
BorderColor string `json:"borderColor"` // 边框色
|
||||
BorderLight string `json:"borderLight"` // 浅色边框
|
||||
|
||||
// 搜索匹配
|
||||
// 搜索和匹配
|
||||
SearchMatch string `json:"searchMatch"` // 搜索匹配
|
||||
MatchingBracket string `json:"matchingBracket"` // 匹配括号
|
||||
}
|
||||
|
||||
// Theme 主题数据库模型
|
||||
type Theme struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Type ThemeType `db:"type" json:"type"`
|
||||
Colors ThemeColorConfig `db:"colors" json:"colors"`
|
||||
IsDefault bool `db:"is_default" json:"isDefault"`
|
||||
CreatedAt string `db:"created_at" json:"createdAt"`
|
||||
UpdatedAt string `db:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
// Value 实现 driver.Valuer 接口,用于将 ThemeColorConfig 存储到数据库
|
||||
func (tc ThemeColorConfig) Value() (driver.Value, error) {
|
||||
return json.Marshal(tc)
|
||||
@@ -85,18 +91,37 @@ func (tc *ThemeColorConfig) Scan(value interface{}) error {
|
||||
return json.Unmarshal(bytes, tc)
|
||||
}
|
||||
|
||||
// NewDefaultDarkTheme 创建默认深色主题配置
|
||||
// Theme 主题数据库模型
|
||||
type Theme struct {
|
||||
ID int `db:"id" json:"id"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Type ThemeType `db:"type" json:"type"`
|
||||
Colors ThemeColorConfig `db:"colors" json:"colors"`
|
||||
IsDefault bool `db:"is_default" json:"isDefault"`
|
||||
CreatedAt string `db:"created_at" json:"createdAt"`
|
||||
UpdatedAt string `db:"updated_at" json:"updatedAt"`
|
||||
}
|
||||
|
||||
// NewDefaultDarkTheme 创建默认深色主题配置(与前端 defaultDarkColors 完全一致)
|
||||
func NewDefaultDarkTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
// 主题信息
|
||||
Name: "default-dark",
|
||||
Dark: true,
|
||||
|
||||
// 基础色调
|
||||
Background: "#252B37",
|
||||
BackgroundSecondary: "#213644",
|
||||
Surface: "#474747",
|
||||
DropdownBackground: "#252B37",
|
||||
DropdownBorder: "#ffffff19",
|
||||
|
||||
// 文本颜色
|
||||
Foreground: "#9BB586",
|
||||
ForegroundSecondary: "#9c9c9c",
|
||||
|
||||
// 语法高亮
|
||||
Comment: "#6272a4",
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
Keyword: "#ff79c6",
|
||||
String: "#f1fa8c",
|
||||
Function: "#50fa7b",
|
||||
@@ -105,6 +130,15 @@ func NewDefaultDarkTheme() *ThemeColorConfig {
|
||||
Variable: "#8fbcbb",
|
||||
Type: "#8be9fd",
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
Constant: "#bd93f9",
|
||||
Storage: "#ff79c6",
|
||||
Parameter: "#8fbcbb",
|
||||
Class: "#8be9fd",
|
||||
Heading: "#ff79c6",
|
||||
Invalid: "#d30102",
|
||||
Regexp: "#f1fa8c",
|
||||
|
||||
// 界面元素
|
||||
Cursor: "#ffffff",
|
||||
Selection: "#0865a9",
|
||||
@@ -113,28 +147,36 @@ func NewDefaultDarkTheme() *ThemeColorConfig {
|
||||
LineNumber: "#ffffff26",
|
||||
ActiveLineNumber: "#ffffff99",
|
||||
|
||||
// 边框分割线
|
||||
// 边框和分割线
|
||||
BorderColor: "#1e222a",
|
||||
BorderLight: "#ffffff1a",
|
||||
BorderLight: "#ffffff19",
|
||||
|
||||
// 搜索匹配
|
||||
// 搜索和匹配
|
||||
SearchMatch: "#8fbcbb",
|
||||
MatchingBracket: "#ffffff1a",
|
||||
MatchingBracket: "#ffffff19",
|
||||
}
|
||||
}
|
||||
|
||||
// NewDefaultLightTheme 创建默认浅色主题配置
|
||||
// NewDefaultLightTheme 创建默认浅色主题配置(与前端 defaultLightColors 完全一致)
|
||||
func NewDefaultLightTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
// 主题信息
|
||||
Name: "default-light",
|
||||
Dark: false,
|
||||
|
||||
// 基础色调
|
||||
Background: "#ffffff",
|
||||
BackgroundSecondary: "#f1faf1",
|
||||
Surface: "#f5f5f5",
|
||||
DropdownBackground: "#ffffff",
|
||||
DropdownBorder: "#e1e4e8",
|
||||
|
||||
// 文本颜色
|
||||
Foreground: "#444d56",
|
||||
ForegroundSecondary: "#6a737d",
|
||||
|
||||
// 语法高亮
|
||||
Comment: "#6a737d",
|
||||
|
||||
// 语法高亮色 - 核心
|
||||
Keyword: "#d73a49",
|
||||
String: "#032f62",
|
||||
Function: "#005cc5",
|
||||
@@ -143,6 +185,15 @@ func NewDefaultLightTheme() *ThemeColorConfig {
|
||||
Variable: "#24292e",
|
||||
Type: "#6f42c1",
|
||||
|
||||
// 语法高亮色 - 扩展
|
||||
Constant: "#005cc5",
|
||||
Storage: "#d73a49",
|
||||
Parameter: "#24292e",
|
||||
Class: "#6f42c1",
|
||||
Heading: "#d73a49",
|
||||
Invalid: "#cb2431",
|
||||
Regexp: "#032f62",
|
||||
|
||||
// 界面元素
|
||||
Cursor: "#000000",
|
||||
Selection: "#77baff",
|
||||
@@ -151,12 +202,578 @@ func NewDefaultLightTheme() *ThemeColorConfig {
|
||||
LineNumber: "#00000040",
|
||||
ActiveLineNumber: "#000000aa",
|
||||
|
||||
// 边框分割线
|
||||
// 边框和分割线
|
||||
BorderColor: "#dfdfdf",
|
||||
BorderLight: "#0000000c",
|
||||
|
||||
// 搜索匹配
|
||||
// 搜索和匹配
|
||||
SearchMatch: "#005cc5",
|
||||
MatchingBracket: "#00000019",
|
||||
}
|
||||
}
|
||||
|
||||
// NewDraculaTheme 创建 Dracula 深色主题配置
|
||||
func NewDraculaTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "dracula",
|
||||
Dark: true,
|
||||
|
||||
Background: "#282A36",
|
||||
BackgroundSecondary: "#282A36",
|
||||
Surface: "#282A36",
|
||||
DropdownBackground: "#282A36",
|
||||
DropdownBorder: "#191A21",
|
||||
|
||||
Foreground: "#F8F8F2",
|
||||
ForegroundSecondary: "#F8F8F2",
|
||||
Comment: "#6272A4",
|
||||
|
||||
Keyword: "#FF79C6",
|
||||
String: "#F1FA8C",
|
||||
Function: "#50FA7B",
|
||||
Number: "#BD93F9",
|
||||
Operator: "#FF79C6",
|
||||
Variable: "#F8F8F2",
|
||||
Type: "#8BE9FD",
|
||||
|
||||
Constant: "#BD93F9",
|
||||
Storage: "#FF79C6",
|
||||
Parameter: "#F8F8F2",
|
||||
Class: "#8BE9FD",
|
||||
Heading: "#BD93F9",
|
||||
Invalid: "#FF5555",
|
||||
Regexp: "#F1FA8C",
|
||||
|
||||
Cursor: "#F8F8F2",
|
||||
Selection: "#44475A",
|
||||
SelectionBlur: "#44475A",
|
||||
ActiveLine: "#53576c22",
|
||||
LineNumber: "#6272A4",
|
||||
ActiveLineNumber: "#F8F8F2",
|
||||
|
||||
BorderColor: "#191A21",
|
||||
BorderLight: "#F8F8F219",
|
||||
|
||||
SearchMatch: "#50FA7B",
|
||||
MatchingBracket: "#44475A",
|
||||
}
|
||||
}
|
||||
|
||||
// NewAuraTheme 创建 Aura 深色主题配置
|
||||
func NewAuraTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "aura",
|
||||
Dark: true,
|
||||
|
||||
Background: "#21202e",
|
||||
BackgroundSecondary: "#21202e",
|
||||
Surface: "#21202e",
|
||||
DropdownBackground: "#21202e",
|
||||
DropdownBorder: "#3b334b",
|
||||
|
||||
Foreground: "#edecee",
|
||||
ForegroundSecondary: "#edecee",
|
||||
Comment: "#6d6d6d",
|
||||
|
||||
Keyword: "#a277ff",
|
||||
String: "#61ffca",
|
||||
Function: "#ffca85",
|
||||
Number: "#61ffca",
|
||||
Operator: "#a277ff",
|
||||
Variable: "#edecee",
|
||||
Type: "#82e2ff",
|
||||
|
||||
Constant: "#61ffca",
|
||||
Storage: "#a277ff",
|
||||
Parameter: "#edecee",
|
||||
Class: "#82e2ff",
|
||||
Heading: "#a277ff",
|
||||
Invalid: "#ff6767",
|
||||
Regexp: "#61ffca",
|
||||
|
||||
Cursor: "#a277ff",
|
||||
Selection: "#3d375e7f",
|
||||
SelectionBlur: "#3d375e7f",
|
||||
ActiveLine: "#4d4b6622",
|
||||
LineNumber: "#a394f033",
|
||||
ActiveLineNumber: "#cdccce",
|
||||
|
||||
BorderColor: "#3b334b",
|
||||
BorderLight: "#edecee19",
|
||||
|
||||
SearchMatch: "#61ffca",
|
||||
MatchingBracket: "#a394f033",
|
||||
}
|
||||
}
|
||||
|
||||
// NewGitHubDarkTheme 创建 GitHub Dark 主题配置
|
||||
func NewGitHubDarkTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "github-dark",
|
||||
Dark: true,
|
||||
|
||||
Background: "#24292e",
|
||||
BackgroundSecondary: "#24292e",
|
||||
Surface: "#24292e",
|
||||
DropdownBackground: "#24292e",
|
||||
DropdownBorder: "#1b1f23",
|
||||
|
||||
Foreground: "#d1d5da",
|
||||
ForegroundSecondary: "#d1d5da",
|
||||
Comment: "#6a737d",
|
||||
|
||||
Keyword: "#f97583",
|
||||
String: "#9ecbff",
|
||||
Function: "#79b8ff",
|
||||
Number: "#79b8ff",
|
||||
Operator: "#f97583",
|
||||
Variable: "#ffab70",
|
||||
Type: "#79b8ff",
|
||||
|
||||
Constant: "#79b8ff",
|
||||
Storage: "#f97583",
|
||||
Parameter: "#e1e4e8",
|
||||
Class: "#b392f0",
|
||||
Heading: "#79b8ff",
|
||||
Invalid: "#f97583",
|
||||
Regexp: "#9ecbff",
|
||||
|
||||
Cursor: "#c8e1ff",
|
||||
Selection: "#3392FF44",
|
||||
SelectionBlur: "#3392FF44",
|
||||
ActiveLine: "#4d566022",
|
||||
LineNumber: "#444d56",
|
||||
ActiveLineNumber: "#e1e4e8",
|
||||
|
||||
BorderColor: "#1b1f23",
|
||||
BorderLight: "#d1d5da19",
|
||||
|
||||
SearchMatch: "#79b8ff",
|
||||
MatchingBracket: "#17E5E650",
|
||||
}
|
||||
}
|
||||
|
||||
// NewMaterialDarkTheme 创建 Material Dark 主题配置
|
||||
func NewMaterialDarkTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "material-dark",
|
||||
Dark: true,
|
||||
|
||||
Background: "#263238",
|
||||
BackgroundSecondary: "#263238",
|
||||
Surface: "#263238",
|
||||
DropdownBackground: "#263238",
|
||||
DropdownBorder: "#FFFFFF10",
|
||||
|
||||
Foreground: "#EEFFFF",
|
||||
ForegroundSecondary: "#EEFFFF",
|
||||
Comment: "#546E7A",
|
||||
|
||||
Keyword: "#C792EA",
|
||||
String: "#C3E88D",
|
||||
Function: "#82AAFF",
|
||||
Number: "#F78C6C",
|
||||
Operator: "#C792EA",
|
||||
Variable: "#EEFFFF",
|
||||
Type: "#B2CCD6",
|
||||
|
||||
Constant: "#F78C6C",
|
||||
Storage: "#C792EA",
|
||||
Parameter: "#EEFFFF",
|
||||
Class: "#FFCB6B",
|
||||
Heading: "#C3E88D",
|
||||
Invalid: "#FF5370",
|
||||
Regexp: "#89DDFF",
|
||||
|
||||
Cursor: "#FFCC00",
|
||||
Selection: "#80CBC420",
|
||||
SelectionBlur: "#80CBC420",
|
||||
ActiveLine: "#4c616c22",
|
||||
LineNumber: "#37474F",
|
||||
ActiveLineNumber: "#607a86",
|
||||
|
||||
BorderColor: "#FFFFFF10",
|
||||
BorderLight: "#EEFFFF19",
|
||||
|
||||
SearchMatch: "#82AAFF",
|
||||
MatchingBracket: "#263238",
|
||||
}
|
||||
}
|
||||
|
||||
// NewOneDarkTheme 创建 One Dark 主题配置
|
||||
func NewOneDarkTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "one-dark",
|
||||
Dark: true,
|
||||
|
||||
Background: "#282c34",
|
||||
BackgroundSecondary: "#2c313a",
|
||||
Surface: "#353a42",
|
||||
DropdownBackground: "#21252b",
|
||||
DropdownBorder: "#7d8799",
|
||||
|
||||
Foreground: "#abb2bf",
|
||||
ForegroundSecondary: "#7d8799",
|
||||
Comment: "#7d8799",
|
||||
|
||||
Keyword: "#c678dd",
|
||||
String: "#98c379",
|
||||
Function: "#61afef",
|
||||
Number: "#e5c07b",
|
||||
Operator: "#56b6c2",
|
||||
Variable: "#e06c75",
|
||||
Type: "#e5c07b",
|
||||
|
||||
Constant: "#d19a66",
|
||||
Storage: "#c678dd",
|
||||
Parameter: "#e06c75",
|
||||
Class: "#e5c07b",
|
||||
Heading: "#e06c75",
|
||||
Invalid: "#ffffff",
|
||||
Regexp: "#56b6c2",
|
||||
|
||||
Cursor: "#528bff",
|
||||
Selection: "#3E4451",
|
||||
SelectionBlur: "#3E4451",
|
||||
ActiveLine: "#6699ff0b",
|
||||
LineNumber: "#7d8799",
|
||||
ActiveLineNumber: "#abb2bf",
|
||||
|
||||
BorderColor: "#21252b",
|
||||
BorderLight: "#abb2bf19",
|
||||
|
||||
SearchMatch: "#61afef",
|
||||
MatchingBracket: "#bad0f847",
|
||||
}
|
||||
}
|
||||
|
||||
// NewSolarizedDarkTheme 创建 Solarized Dark 主题配置
|
||||
func NewSolarizedDarkTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "solarized-dark",
|
||||
Dark: true,
|
||||
|
||||
Background: "#002B36",
|
||||
BackgroundSecondary: "#002B36",
|
||||
Surface: "#002B36",
|
||||
DropdownBackground: "#002B36",
|
||||
DropdownBorder: "#2AA19899",
|
||||
|
||||
Foreground: "#93A1A1",
|
||||
ForegroundSecondary: "#93A1A1",
|
||||
Comment: "#586E75",
|
||||
|
||||
Keyword: "#859900",
|
||||
String: "#2AA198",
|
||||
Function: "#268BD2",
|
||||
Number: "#D33682",
|
||||
Operator: "#859900",
|
||||
Variable: "#268BD2",
|
||||
Type: "#CB4B16",
|
||||
|
||||
Constant: "#CB4B16",
|
||||
Storage: "#93A1A1",
|
||||
Parameter: "#268BD2",
|
||||
Class: "#CB4B16",
|
||||
Heading: "#268BD2",
|
||||
Invalid: "#DC322F",
|
||||
Regexp: "#DC322F",
|
||||
|
||||
Cursor: "#D30102",
|
||||
Selection: "#274642",
|
||||
SelectionBlur: "#274642",
|
||||
ActiveLine: "#005b7022",
|
||||
LineNumber: "#93A1A1",
|
||||
ActiveLineNumber: "#949494",
|
||||
|
||||
BorderColor: "#073642",
|
||||
BorderLight: "#93A1A119",
|
||||
|
||||
SearchMatch: "#2AA198",
|
||||
MatchingBracket: "#073642",
|
||||
}
|
||||
}
|
||||
|
||||
// NewTokyoNightTheme 创建 Tokyo Night 主题配置
|
||||
func NewTokyoNightTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "tokyo-night",
|
||||
Dark: true,
|
||||
|
||||
Background: "#1a1b26",
|
||||
BackgroundSecondary: "#1a1b26",
|
||||
Surface: "#1a1b26",
|
||||
DropdownBackground: "#1a1b26",
|
||||
DropdownBorder: "#787c99",
|
||||
|
||||
Foreground: "#787c99",
|
||||
ForegroundSecondary: "#787c99",
|
||||
Comment: "#444b6a",
|
||||
|
||||
Keyword: "#bb9af7",
|
||||
String: "#9ece6a",
|
||||
Function: "#7aa2f7",
|
||||
Number: "#ff9e64",
|
||||
Operator: "#bb9af7",
|
||||
Variable: "#c0caf5",
|
||||
Type: "#0db9d7",
|
||||
|
||||
Constant: "#bb9af7",
|
||||
Storage: "#bb9af7",
|
||||
Parameter: "#c0caf5",
|
||||
Class: "#c0caf5",
|
||||
Heading: "#89ddff",
|
||||
Invalid: "#ff5370",
|
||||
Regexp: "#b4f9f8",
|
||||
|
||||
Cursor: "#c0caf5",
|
||||
Selection: "#515c7e40",
|
||||
SelectionBlur: "#515c7e40",
|
||||
ActiveLine: "#43455c22",
|
||||
LineNumber: "#363b54",
|
||||
ActiveLineNumber: "#737aa2",
|
||||
|
||||
BorderColor: "#16161e",
|
||||
BorderLight: "#787c9919",
|
||||
|
||||
SearchMatch: "#7aa2f7",
|
||||
MatchingBracket: "#16161e",
|
||||
}
|
||||
}
|
||||
|
||||
// NewTokyoNightStormTheme 创建 Tokyo Night Storm 主题配置
|
||||
func NewTokyoNightStormTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "tokyo-night-storm",
|
||||
Dark: true,
|
||||
|
||||
Background: "#24283b",
|
||||
BackgroundSecondary: "#24283b",
|
||||
Surface: "#24283b",
|
||||
DropdownBackground: "#24283b",
|
||||
DropdownBorder: "#7982a9",
|
||||
|
||||
Foreground: "#7982a9",
|
||||
ForegroundSecondary: "#7982a9",
|
||||
Comment: "#565f89",
|
||||
|
||||
Keyword: "#bb9af7",
|
||||
String: "#9ece6a",
|
||||
Function: "#7aa2f7",
|
||||
Number: "#ff9e64",
|
||||
Operator: "#bb9af7",
|
||||
Variable: "#c0caf5",
|
||||
Type: "#2ac3de",
|
||||
|
||||
Constant: "#bb9af7",
|
||||
Storage: "#bb9af7",
|
||||
Parameter: "#c0caf5",
|
||||
Class: "#c0caf5",
|
||||
Heading: "#89ddff",
|
||||
Invalid: "#ff5370",
|
||||
Regexp: "#b4f9f8",
|
||||
|
||||
Cursor: "#c0caf5",
|
||||
Selection: "#6f7bb630",
|
||||
SelectionBlur: "#6f7bb630",
|
||||
ActiveLine: "#4d547722",
|
||||
LineNumber: "#3b4261",
|
||||
ActiveLineNumber: "#737aa2",
|
||||
|
||||
BorderColor: "#1f2335",
|
||||
BorderLight: "#7982a919",
|
||||
|
||||
SearchMatch: "#7aa2f7",
|
||||
MatchingBracket: "#1f2335",
|
||||
}
|
||||
}
|
||||
|
||||
// 浅色主题预设配置
|
||||
|
||||
// NewGitHubLightTheme 创建 GitHub Light 主题配置
|
||||
func NewGitHubLightTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "github-light",
|
||||
Dark: false,
|
||||
|
||||
Background: "#fff",
|
||||
BackgroundSecondary: "#fff",
|
||||
Surface: "#fff",
|
||||
DropdownBackground: "#fff",
|
||||
DropdownBorder: "#e1e4e8",
|
||||
|
||||
Foreground: "#444d56",
|
||||
ForegroundSecondary: "#444d56",
|
||||
Comment: "#6a737d",
|
||||
|
||||
Keyword: "#d73a49",
|
||||
String: "#032f62",
|
||||
Function: "#005cc5",
|
||||
Number: "#005cc5",
|
||||
Operator: "#d73a49",
|
||||
Variable: "#e36209",
|
||||
Type: "#005cc5",
|
||||
|
||||
Constant: "#005cc5",
|
||||
Storage: "#d73a49",
|
||||
Parameter: "#24292e",
|
||||
Class: "#6f42c1",
|
||||
Heading: "#005cc5",
|
||||
Invalid: "#cb2431",
|
||||
Regexp: "#032f62",
|
||||
|
||||
Cursor: "#044289",
|
||||
Selection: "#0366d625",
|
||||
SelectionBlur: "#0366d625",
|
||||
ActiveLine: "#c6c6c622",
|
||||
LineNumber: "#1b1f234d",
|
||||
ActiveLineNumber: "#24292e",
|
||||
|
||||
BorderColor: "#e1e4e8",
|
||||
BorderLight: "#444d5619",
|
||||
|
||||
SearchMatch: "#005cc5",
|
||||
MatchingBracket: "#34d05840",
|
||||
}
|
||||
}
|
||||
|
||||
// NewMaterialLightTheme 创建 Material Light 主题配置
|
||||
func NewMaterialLightTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "material-light",
|
||||
Dark: false,
|
||||
|
||||
Background: "#FAFAFA",
|
||||
BackgroundSecondary: "#FAFAFA",
|
||||
Surface: "#FAFAFA",
|
||||
DropdownBackground: "#FAFAFA",
|
||||
DropdownBorder: "#00000010",
|
||||
|
||||
Foreground: "#90A4AE",
|
||||
ForegroundSecondary: "#90A4AE",
|
||||
Comment: "#90A4AE",
|
||||
|
||||
Keyword: "#7C4DFF",
|
||||
String: "#91B859",
|
||||
Function: "#6182B8",
|
||||
Number: "#F76D47",
|
||||
Operator: "#7C4DFF",
|
||||
Variable: "#90A4AE",
|
||||
Type: "#8796B0",
|
||||
|
||||
Constant: "#F76D47",
|
||||
Storage: "#7C4DFF",
|
||||
Parameter: "#90A4AE",
|
||||
Class: "#FFB62C",
|
||||
Heading: "#91B859",
|
||||
Invalid: "#E53935",
|
||||
Regexp: "#39ADB5",
|
||||
|
||||
Cursor: "#272727",
|
||||
Selection: "#80CBC440",
|
||||
SelectionBlur: "#80CBC440",
|
||||
ActiveLine: "#c2c2c222",
|
||||
LineNumber: "#CFD8DC",
|
||||
ActiveLineNumber: "#7E939E",
|
||||
|
||||
BorderColor: "#00000010",
|
||||
BorderLight: "#90A4AE19",
|
||||
|
||||
SearchMatch: "#6182B8",
|
||||
MatchingBracket: "#FAFAFA",
|
||||
}
|
||||
}
|
||||
|
||||
// NewSolarizedLightTheme 创建 Solarized Light 主题配置
|
||||
func NewSolarizedLightTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "solarized-light",
|
||||
Dark: false,
|
||||
|
||||
Background: "#FDF6E3",
|
||||
BackgroundSecondary: "#FDF6E3",
|
||||
Surface: "#FDF6E3",
|
||||
DropdownBackground: "#FDF6E3",
|
||||
DropdownBorder: "#D3AF86",
|
||||
|
||||
Foreground: "#586E75",
|
||||
ForegroundSecondary: "#586E75",
|
||||
Comment: "#93A1A1",
|
||||
|
||||
Keyword: "#859900",
|
||||
String: "#2AA198",
|
||||
Function: "#268BD2",
|
||||
Number: "#D33682",
|
||||
Operator: "#859900",
|
||||
Variable: "#268BD2",
|
||||
Type: "#CB4B16",
|
||||
|
||||
Constant: "#CB4B16",
|
||||
Storage: "#586E75",
|
||||
Parameter: "#268BD2",
|
||||
Class: "#CB4B16",
|
||||
Heading: "#268BD2",
|
||||
Invalid: "#DC322F",
|
||||
Regexp: "#DC322F",
|
||||
|
||||
Cursor: "#657B83",
|
||||
Selection: "#EEE8D5",
|
||||
SelectionBlur: "#EEE8D5",
|
||||
ActiveLine: "#d5bd5c22",
|
||||
LineNumber: "#586E75",
|
||||
ActiveLineNumber: "#567983",
|
||||
|
||||
BorderColor: "#EEE8D5",
|
||||
BorderLight: "#586E7519",
|
||||
|
||||
SearchMatch: "#268BD2",
|
||||
MatchingBracket: "#EEE8D5",
|
||||
}
|
||||
}
|
||||
|
||||
// NewTokyoNightDayTheme 创建 Tokyo Night Day 主题配置
|
||||
func NewTokyoNightDayTheme() *ThemeColorConfig {
|
||||
return &ThemeColorConfig{
|
||||
Name: "tokyo-night-day",
|
||||
Dark: false,
|
||||
|
||||
Background: "#e1e2e7",
|
||||
BackgroundSecondary: "#e1e2e7",
|
||||
Surface: "#e1e2e7",
|
||||
DropdownBackground: "#e1e2e7",
|
||||
DropdownBorder: "#6a6f8e",
|
||||
|
||||
Foreground: "#6a6f8e",
|
||||
ForegroundSecondary: "#6a6f8e",
|
||||
Comment: "#9da3c2",
|
||||
|
||||
Keyword: "#9854f1",
|
||||
String: "#587539",
|
||||
Function: "#2e7de9",
|
||||
Number: "#b15c00",
|
||||
Operator: "#9854f1",
|
||||
Variable: "#3760bf",
|
||||
Type: "#07879d",
|
||||
|
||||
Constant: "#9854f1",
|
||||
Storage: "#9854f1",
|
||||
Parameter: "#3760bf",
|
||||
Class: "#3760bf",
|
||||
Heading: "#006a83",
|
||||
Invalid: "#ff3e64",
|
||||
Regexp: "#2e5857",
|
||||
|
||||
Cursor: "#3760bf",
|
||||
Selection: "#8591b840",
|
||||
SelectionBlur: "#8591b840",
|
||||
ActiveLine: "#a7aaba22",
|
||||
LineNumber: "#b3b6cd",
|
||||
ActiveLineNumber: "#68709a",
|
||||
|
||||
BorderColor: "#e9e9ec",
|
||||
BorderLight: "#6a6f8e19",
|
||||
|
||||
SearchMatch: "#2e7de9",
|
||||
MatchingBracket: "#e9e9ec",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,13 +67,12 @@ CREATE TABLE IF NOT EXISTS key_bindings (
|
||||
sqlCreateThemesTable = `
|
||||
CREATE TABLE IF NOT EXISTS themes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT NOT NULL,
|
||||
colors TEXT NOT NULL,
|
||||
is_default INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
UNIQUE(type, is_default)
|
||||
updated_at TEXT NOT NULL
|
||||
)`
|
||||
)
|
||||
|
||||
@@ -222,6 +221,8 @@ func (ds *DatabaseService) createIndexes() error {
|
||||
// Themes indexes
|
||||
`CREATE INDEX IF NOT EXISTS idx_themes_type ON themes(type)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_themes_is_default ON themes(is_default)`,
|
||||
// 条件唯一索引:确保每种类型只能有一个默认主题
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS idx_themes_type_default ON themes(type) WHERE is_default = 1`,
|
||||
}
|
||||
|
||||
for _, index := range indexes {
|
||||
|
||||
@@ -3,6 +3,7 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
"voidraft/internal/models"
|
||||
@@ -43,77 +44,124 @@ func (ts *ThemeService) getDB() *sql.DB {
|
||||
return ts.databaseService.db
|
||||
}
|
||||
|
||||
// initializeDefaultThemes 初始化默认主题
|
||||
// initializeDefaultThemes 初始化所有预设主题
|
||||
func (ts *ThemeService) initializeDefaultThemes() error {
|
||||
db := ts.getDB()
|
||||
if db == nil {
|
||||
return fmt.Errorf("database not available")
|
||||
}
|
||||
|
||||
// 检查是否已存在默认主题
|
||||
var count int
|
||||
err := db.QueryRow("SELECT COUNT(*) FROM themes WHERE is_default = 1").Scan(&count)
|
||||
// 获取所有已存在的主题名称
|
||||
existingThemes := make(map[string]bool)
|
||||
rows, err := db.Query("SELECT name FROM themes")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check existing themes: %w", err)
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
return nil // 默认主题已存在
|
||||
}
|
||||
|
||||
// 创建默认深色主题
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
darkTheme := &models.Theme{
|
||||
Name: "Default Dark",
|
||||
Type: models.ThemeTypeDark,
|
||||
Colors: *models.NewDefaultDarkTheme(),
|
||||
IsDefault: true,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
// 创建默认浅色主题
|
||||
lightTheme := &models.Theme{
|
||||
Name: "Default Light",
|
||||
Type: models.ThemeTypeLight,
|
||||
Colors: *models.NewDefaultLightTheme(),
|
||||
IsDefault: true,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
// 插入默认主题
|
||||
if _, err := ts.CreateTheme(darkTheme); err != nil {
|
||||
return fmt.Errorf("failed to create default dark theme: %w", err)
|
||||
}
|
||||
|
||||
if _, err := ts.CreateTheme(lightTheme); err != nil {
|
||||
return fmt.Errorf("failed to create default light theme: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDefaultThemes 获取默认主题
|
||||
func (ts *ThemeService) GetDefaultThemes() (map[string]*models.Theme, error) {
|
||||
query := `
|
||||
SELECT id, name, type, colors, is_default, created_at, updated_at
|
||||
FROM themes
|
||||
WHERE is_default = 1
|
||||
ORDER BY type
|
||||
`
|
||||
|
||||
db := ts.getDB()
|
||||
rows, err := db.Query(query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query default themes: %w", err)
|
||||
return fmt.Errorf("failed to query existing themes: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
themes := make(map[string]*models.Theme)
|
||||
for rows.Next() {
|
||||
var name string
|
||||
if err := rows.Scan(&name); err != nil {
|
||||
return fmt.Errorf("failed to scan theme name: %w", err)
|
||||
}
|
||||
existingThemes[name] = true
|
||||
}
|
||||
|
||||
// 定义所有预设主题配置
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
presetThemes := []struct {
|
||||
config *models.ThemeColorConfig
|
||||
themeType models.ThemeType
|
||||
isDefault bool
|
||||
}{
|
||||
// 默认主题
|
||||
{models.NewDefaultDarkTheme(), models.ThemeTypeDark, true},
|
||||
{models.NewDefaultLightTheme(), models.ThemeTypeLight, true},
|
||||
|
||||
// 深色主题预设
|
||||
{models.NewDraculaTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewAuraTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewGitHubDarkTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewMaterialDarkTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewOneDarkTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewSolarizedDarkTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewTokyoNightTheme(), models.ThemeTypeDark, false},
|
||||
{models.NewTokyoNightStormTheme(), models.ThemeTypeDark, false},
|
||||
|
||||
// 浅色主题预设
|
||||
{models.NewGitHubLightTheme(), models.ThemeTypeLight, false},
|
||||
{models.NewMaterialLightTheme(), models.ThemeTypeLight, false},
|
||||
{models.NewSolarizedLightTheme(), models.ThemeTypeLight, false},
|
||||
{models.NewTokyoNightDayTheme(), models.ThemeTypeLight, false},
|
||||
}
|
||||
|
||||
// 筛选出需要创建的主题
|
||||
var themesToCreate []*models.Theme
|
||||
for _, preset := range presetThemes {
|
||||
if !existingThemes[preset.config.Name] {
|
||||
themesToCreate = append(themesToCreate, &models.Theme{
|
||||
Name: preset.config.Name,
|
||||
Type: preset.themeType,
|
||||
Colors: *preset.config,
|
||||
IsDefault: preset.isDefault,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(themesToCreate) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 批量插入主题
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
stmt, err := tx.Prepare(`
|
||||
INSERT INTO themes (name, type, colors, is_default, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare statement: %w", err)
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
for _, theme := range themesToCreate {
|
||||
_, err := stmt.Exec(
|
||||
theme.Name,
|
||||
theme.Type,
|
||||
theme.Colors,
|
||||
theme.IsDefault,
|
||||
theme.CreatedAt,
|
||||
theme.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to insert theme %s: %w", theme.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetThemeByID 根据ID获取主题
|
||||
func (ts *ThemeService) GetThemeByID(id int) (*models.Theme, error) {
|
||||
query := `
|
||||
SELECT id, name, type, colors, is_default, created_at, updated_at
|
||||
FROM themes
|
||||
WHERE id = ?
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
theme := &models.Theme{}
|
||||
err := rows.Scan(
|
||||
db := ts.getDB()
|
||||
err := db.QueryRow(query, id).Scan(
|
||||
&theme.ID,
|
||||
&theme.Name,
|
||||
&theme.Type,
|
||||
@@ -122,17 +170,15 @@ func (ts *ThemeService) GetDefaultThemes() (map[string]*models.Theme, error) {
|
||||
&theme.CreatedAt,
|
||||
&theme.UpdatedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan theme: %w", err)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, fmt.Errorf("theme not found with id: %d", id)
|
||||
}
|
||||
themes[string(theme.Type)] = theme
|
||||
return nil, fmt.Errorf("failed to get theme by id: %w", err)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate themes: %w", err)
|
||||
}
|
||||
|
||||
return themes, nil
|
||||
return theme, nil
|
||||
}
|
||||
|
||||
// GetThemeByType 根据类型获取默认主题
|
||||
@@ -166,37 +212,123 @@ func (ts *ThemeService) GetThemeByType(themeType models.ThemeType) (*models.Them
|
||||
return theme, nil
|
||||
}
|
||||
|
||||
// UpdateThemeColors 更新主题颜色
|
||||
func (ts *ThemeService) UpdateThemeColors(themeType models.ThemeType, colors models.ThemeColorConfig) error {
|
||||
// GetThemesByType 根据类型获取所有主题
|
||||
func (ts *ThemeService) GetThemesByType(themeType models.ThemeType) ([]*models.Theme, error) {
|
||||
query := `
|
||||
UPDATE themes
|
||||
SET colors = ?, updated_at = ?
|
||||
WHERE type = ? AND is_default = 1
|
||||
SELECT id, name, type, colors, is_default, created_at, updated_at
|
||||
FROM themes
|
||||
WHERE type = ?
|
||||
ORDER BY is_default DESC, name ASC
|
||||
`
|
||||
|
||||
db := ts.getDB()
|
||||
_, err := db.Exec(query, colors, time.Now().Format("2006-01-02 15:04:05"), themeType)
|
||||
rows, err := db.Query(query, themeType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update theme colors: %w", err)
|
||||
return nil, fmt.Errorf("failed to query themes by type: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var themes []*models.Theme
|
||||
for rows.Next() {
|
||||
theme := &models.Theme{}
|
||||
err := rows.Scan(
|
||||
&theme.ID,
|
||||
&theme.Name,
|
||||
&theme.Type,
|
||||
&theme.Colors,
|
||||
&theme.IsDefault,
|
||||
&theme.CreatedAt,
|
||||
&theme.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan theme: %w", err)
|
||||
}
|
||||
themes = append(themes, theme)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("failed to iterate themes: %w", err)
|
||||
}
|
||||
|
||||
return themes, nil
|
||||
}
|
||||
|
||||
// UpdateTheme 更新主题
|
||||
func (ts *ThemeService) UpdateTheme(id int, colors models.ThemeColorConfig) error {
|
||||
query := `
|
||||
UPDATE themes
|
||||
SET colors = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
db := ts.getDB()
|
||||
result, err := db.Exec(query, colors, time.Now().Format("2006-01-02 15:04:05"), id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update theme: %w", err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get rows affected: %w", err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("theme not found with id: %d", id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetThemeColors 重置主题颜色为默认值
|
||||
func (ts *ThemeService) ResetThemeColors(themeType models.ThemeType) error {
|
||||
var defaultColors models.ThemeColorConfig
|
||||
|
||||
switch themeType {
|
||||
case models.ThemeTypeDark:
|
||||
defaultColors = *models.NewDefaultDarkTheme()
|
||||
case models.ThemeTypeLight:
|
||||
defaultColors = *models.NewDefaultLightTheme()
|
||||
default:
|
||||
return fmt.Errorf("unknown theme type: %s", themeType)
|
||||
// ResetTheme 重置主题为预设配置
|
||||
func (ts *ThemeService) ResetTheme(id int) error {
|
||||
// 先获取主题信息
|
||||
theme, err := ts.GetThemeByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ts.UpdateThemeColors(themeType, defaultColors)
|
||||
// 根据主题名称获取预设配置
|
||||
var presetConfig *models.ThemeColorConfig
|
||||
switch theme.Name {
|
||||
// 默认主题
|
||||
case "default-dark":
|
||||
presetConfig = models.NewDefaultDarkTheme()
|
||||
case "default-light":
|
||||
presetConfig = models.NewDefaultLightTheme()
|
||||
|
||||
// 深色主题预设
|
||||
case "dracula":
|
||||
presetConfig = models.NewDraculaTheme()
|
||||
case "aura":
|
||||
presetConfig = models.NewAuraTheme()
|
||||
case "github-dark":
|
||||
presetConfig = models.NewGitHubDarkTheme()
|
||||
case "material-dark":
|
||||
presetConfig = models.NewMaterialDarkTheme()
|
||||
case "one-dark":
|
||||
presetConfig = models.NewOneDarkTheme()
|
||||
case "solarized-dark":
|
||||
presetConfig = models.NewSolarizedDarkTheme()
|
||||
case "tokyo-night":
|
||||
presetConfig = models.NewTokyoNightTheme()
|
||||
case "tokyo-night-storm":
|
||||
presetConfig = models.NewTokyoNightStormTheme()
|
||||
|
||||
// 浅色主题预设
|
||||
case "github-light":
|
||||
presetConfig = models.NewGitHubLightTheme()
|
||||
case "material-light":
|
||||
presetConfig = models.NewMaterialLightTheme()
|
||||
case "solarized-light":
|
||||
presetConfig = models.NewSolarizedLightTheme()
|
||||
case "tokyo-night-day":
|
||||
presetConfig = models.NewTokyoNightDayTheme()
|
||||
|
||||
default:
|
||||
return fmt.Errorf("no preset configuration found for theme: %s", theme.Name)
|
||||
}
|
||||
|
||||
return ts.UpdateTheme(id, *presetConfig)
|
||||
}
|
||||
|
||||
// CreateTheme 创建新主题
|
||||
@@ -235,7 +367,7 @@ func (ts *ThemeService) GetAllThemes() ([]*models.Theme, error) {
|
||||
query := `
|
||||
SELECT id, name, type, colors, is_default, created_at, updated_at
|
||||
FROM themes
|
||||
ORDER BY is_default DESC, created_at ASC
|
||||
ORDER BY is_default DESC, type DESC, name ASC
|
||||
`
|
||||
|
||||
db := ts.getDB()
|
||||
|
||||
@@ -1 +1 @@
|
||||
VERSION=1.5.0
|
||||
VERSION=1.5.1
|
||||
|
||||
Reference in New Issue
Block a user