дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
Merge remote-tracking branch 'origin/main' into fix/translate-template-text
# Conflicts: # src/platform/locales/text/zh.json
Цей коміт міститься в:
коміт
9a760f8620
78 files changed
+3537
-1409
No files matched your search
@@ -9,14 +9,11 @@
|
||||
*/
|
||||
import tokensCss from "@/styles/tokens.css?raw";
|
||||
import type { TextAttributesOverride } from "./editorSettings";
|
||||
import { BUILTIN_THEMES, isBuiltinTheme, themeKind, type BuiltinThemeId } from "./themes";
|
||||
|
||||
export type SchemeId = "light" | "dark" | "dark-hc";
|
||||
export type SchemeId = BuiltinThemeId;
|
||||
|
||||
export const SCHEMES: ReadonlyArray<{ id: SchemeId; name: string }> = [
|
||||
{ id: "light", name: "Islands Light" },
|
||||
{ id: "dark", name: "Islands Dark" },
|
||||
{ id: "dark-hc", name: "High Contrast" },
|
||||
];
|
||||
export const SCHEMES: ReadonlyArray<{ id: SchemeId; name: string }> = BUILTIN_THEMES.map((t) => ({ id: t.id, name: t.label }));
|
||||
|
||||
export interface AttributeDef {
|
||||
id: string;
|
||||
@@ -167,7 +164,8 @@ function blocks(css: string): Array<{ selectors: string[]; decls: Vars }> {
|
||||
function themeSelectors(id: SchemeId): string[] {
|
||||
if (id === "light") return [':root[data-theme="light"]'];
|
||||
if (id === "dark-hc") return [':root[data-theme="dark-hc"]', ':root[data-theme="dark"][data-contrast="high"]'];
|
||||
return [':root[data-theme="dark"]'];
|
||||
if (id === "dark") return [':root[data-theme="dark"]'];
|
||||
return [`:root[data-theme="${themeKind(id)}"]`, ":root[data-color-theme]", `:root[data-color-theme="${id}"]`];
|
||||
}
|
||||
|
||||
let source: string = tokensCss;
|
||||
@@ -205,13 +203,14 @@ export function schemeTokens(id: SchemeId, css: string = source): Vars {
|
||||
|
||||
/** The scheme the editor shows for `setting` under the current theme. */
|
||||
export function effectiveScheme(setting: string | undefined, root: HTMLElement | null = typeof document !== "undefined" ? document.documentElement : null): SchemeId {
|
||||
if (setting === "light" || setting === "dark" || setting === "dark-hc") return setting;
|
||||
if (isBuiltinTheme(setting)) return setting;
|
||||
return themeScheme(root);
|
||||
}
|
||||
|
||||
/** Scheme belonging to the active IDE theme (`data-theme` / `data-contrast`). */
|
||||
export function themeScheme(root: HTMLElement | null = typeof document !== "undefined" ? document.documentElement : null): SchemeId {
|
||||
if (!root) return "light";
|
||||
if (isBuiltinTheme(root.dataset.colorTheme)) return root.dataset.colorTheme;
|
||||
if (root.dataset.theme === "light") return "light";
|
||||
return root.dataset.contrast === "high" || root.dataset.theme === "dark-hc" ? "dark-hc" : "dark";
|
||||
}
|
||||
|
||||
@@ -633,7 +633,6 @@
|
||||
"Environment": "环境",
|
||||
"Environment variables": "环境变量",
|
||||
"Error Highlighting": "错误高亮",
|
||||
"Solarized Light and Solarized Dark: Ethan Schoonover's Solarized palette.": "Solarized Light 和 Solarized Dark:Ethan Schoonover 的 Solarized 调色板。",
|
||||
"Evaluate": "计算",
|
||||
"Evaluate Expression…": "计算表达式…",
|
||||
"Evaluate expression": "计算表达式",
|
||||
@@ -3643,6 +3642,43 @@
|
||||
"Process comments": "处理注释",
|
||||
"Distraction Free Mode": "无干扰模式",
|
||||
"Exit Distraction Free Mode": "退出无干扰模式",
|
||||
"Show Hidden Files": "显示隐藏文件",
|
||||
"Show Excluded Files": "显示已排除的文件",
|
||||
"Compact Middle Packages": "压缩中间软件包",
|
||||
"Sort Folders First": "文件夹排在前面",
|
||||
"Open Files with Single Click": "单击打开文件",
|
||||
"Expand Directories with Single Click": "单击展开目录",
|
||||
"Enable Preview Tab": "启用预览标签页",
|
||||
"Analyze Dependencies…": "分析依赖…",
|
||||
"Shows a Maven module's dependency tree, version conflicts and where each library comes from": "显示 Maven 模块的依赖树、版本冲突以及每个库的引入路径",
|
||||
"Dependency Analyzer": "依赖分析器",
|
||||
"Search dependencies": "搜索依赖",
|
||||
"Show conflicts only": "仅显示冲突",
|
||||
"All scopes": "所有范围",
|
||||
"Show as List": "以列表显示",
|
||||
"Show as Tree": "以树形显示",
|
||||
"Dependency trees may be out of date": "依赖树可能已过期",
|
||||
"Dependency trees are read when Maven projects are reloaded": "重新加载 Maven 项目时会读取依赖树",
|
||||
"No Maven modules": "没有 Maven 模块",
|
||||
"Dependencies": "依赖",
|
||||
"No dependencies match the filter": "没有符合筛选条件的依赖",
|
||||
"No dependencies": "没有依赖",
|
||||
"Select a dependency to see its usages": "选择一个依赖以查看其用法",
|
||||
"Versions requested": "请求的版本",
|
||||
"omitted": "已省略",
|
||||
"resolved": "已解析",
|
||||
"omitted for conflict with {version}": "因与 {version} 冲突而省略",
|
||||
"omitted for conflict": "因冲突而省略",
|
||||
"omitted for duplicate": "因重复而省略",
|
||||
"omitted for cycle": "因循环依赖而省略",
|
||||
"version managed from {version}": "版本由 {version} 经依赖管理调整",
|
||||
"Cannot find the declaration": "找不到声明",
|
||||
"Cannot exclude {name}": "无法排除 {name}",
|
||||
"Solarized Light": "Solarized 浅色",
|
||||
"Solarized Dark": "Solarized 深色",
|
||||
"One Light": "One 浅色",
|
||||
"One Dark": "One 深色",
|
||||
"Solarized Light and Solarized Dark: Ethan Schoonover's Solarized palette.": "Solarized Light 和 Solarized Dark:Ethan Schoonover 的 Solarized 调色板。",
|
||||
"Copied reference: {reference}": "已复制引用:{reference}",
|
||||
"{count} lines": "{count} 行",
|
||||
"Preview of {path}": "{path} 的预览",
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { BUILTIN_THEMES, isBuiltinTheme, themeKind } from "./themes";
|
||||
import { _setSchemeSource, effectiveScheme, schemeCss, schemeTokens, themeScheme } from "./colorScheme";
|
||||
import { applyThemeAttributes, resolveTheme, resolveThemeId } from "@/workbench/theme";
|
||||
import { validateSettings } from "@/features/settings/model/schema";
|
||||
import { applyPluginTheme } from "@/features/plugins/bridge";
|
||||
|
||||
const css = readFileSync("src/styles/tokens.css", "utf8");
|
||||
_setSchemeSource(css);
|
||||
afterEach(() => {
|
||||
applyPluginTheme(null);
|
||||
delete document.documentElement.dataset.colorTheme;
|
||||
delete document.documentElement.dataset.contrast;
|
||||
});
|
||||
|
||||
describe("built-in palettes", () => {
|
||||
it.each(BUILTIN_THEMES)("preserves $id through validation and system resolution", ({ id, kind }) => {
|
||||
const a = { theme: id, preferredLightTheme: id, preferredDarkTheme: id };
|
||||
expect(validateSettings({ appearance: a }).appearance).toMatchObject(a);
|
||||
expect(resolveThemeId(a, false)).toBe(id);
|
||||
expect(resolveTheme(id, false)).toBe(kind);
|
||||
expect(resolveThemeId({ ...a, syncWithOs: true }, true)).toBe(id);
|
||||
expect(resolveThemeId({ ...a, theme: "system" }, false)).toBe(id);
|
||||
applyThemeAttributes(id);
|
||||
expect(document.documentElement.dataset.theme).toBe(kind);
|
||||
expect(themeScheme()).toBe(id);
|
||||
expect(effectiveScheme(id)).toBe(id);
|
||||
expect(schemeCss("theme-default", undefined)).toBe("");
|
||||
expect(schemeTokens(id).get("--bg-editor")).not.toContain("var(");
|
||||
});
|
||||
|
||||
it("rejects unknown ids and retains legacy fallbacks", () => {
|
||||
expect(isBuiltinTheme("not-a-theme")).toBe(false);
|
||||
expect(resolveThemeId({ theme: "bad" }, true)).toBe("light");
|
||||
expect(resolveThemeId({ theme: "system", preferredDarkTheme: "bad" }, false)).toBe("dark");
|
||||
expect(themeKind("solarized-light")).toBe("light");
|
||||
});
|
||||
|
||||
// Token coverage of every palette theme: settings/__tests__/contrast.test.ts.
|
||||
it("resolves editor scheme tokens from the palettes", () => {
|
||||
expect(schemeTokens("solarized-light").get("--bg-editor")).toBe("#fdf6e3");
|
||||
expect(schemeTokens("solarized-dark").get("--bg-editor")).toBe("#002b36");
|
||||
expect(schemeTokens("solarized-dark").get("--syn-string")).toBe("#2aa198");
|
||||
expect(schemeTokens("solarized-light").get("--ansi-bright-blue")).toBe("#839496");
|
||||
expect(schemeTokens("one-light").get("--syn-keyword")).toBe("hsl(301, 63%, 40%)");
|
||||
expect(schemeTokens("one-dark").get("--syn-string")).toBe("hsl(95, 38%, 62%)");
|
||||
});
|
||||
|
||||
it("keeps explicit editor schemes and per-scheme edits independent of UI palettes", () => {
|
||||
applyThemeAttributes("solarized-light");
|
||||
expect(schemeCss("one-dark", undefined)).toContain("--bg-editor: hsl(220, 13%, 18%) !important");
|
||||
expect(schemeCss("theme-default", { "solarized-light": { keyword: { foreground: "#123456" } } })).toContain(
|
||||
"--syn-keyword: #123456 !important",
|
||||
);
|
||||
applyThemeAttributes("one-light");
|
||||
expect(schemeCss("theme-default", { "solarized-light": { keyword: { foreground: "#123456" } } })).toBe("");
|
||||
});
|
||||
|
||||
it("clears the palette for plugins and restores it when the plugin is removed", () => {
|
||||
const root = document.documentElement;
|
||||
applyThemeAttributes("one-dark", root);
|
||||
root.dataset.pluginThemeKind = "light";
|
||||
applyThemeAttributes("one-dark", root);
|
||||
expect(root.dataset.colorTheme).toBeUndefined();
|
||||
expect(root.dataset.theme).toBe("light");
|
||||
delete root.dataset.pluginThemeKind;
|
||||
applyThemeAttributes("one-dark", root);
|
||||
expect(root.dataset.colorTheme).toBe("one-dark");
|
||||
applyThemeAttributes("dark-hc", root);
|
||||
expect(root.dataset.colorTheme).toBeUndefined();
|
||||
expect(root.dataset.contrast).toBe("high");
|
||||
applyThemeAttributes("solarized-dark", root);
|
||||
expect(root.dataset.contrast).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/** Stable built-in ids shared by settings, quick switch and editor schemes. */
|
||||
export const BUILTIN_THEMES = [
|
||||
{ id: "light", label: "Islands Light", kind: "light" },
|
||||
{ id: "dark", label: "Islands Dark", kind: "dark" },
|
||||
{ id: "dark-hc", label: "High Contrast", kind: "dark" },
|
||||
{ id: "solarized-light", label: "Solarized Light", kind: "light" },
|
||||
{ id: "solarized-dark", label: "Solarized Dark", kind: "dark" },
|
||||
{ id: "one-light", label: "One Light", kind: "light" },
|
||||
{ id: "one-dark", label: "One Dark", kind: "dark" },
|
||||
] as const;
|
||||
|
||||
export type BuiltinThemeId = (typeof BUILTIN_THEMES)[number]["id"];
|
||||
export const BUILTIN_THEME_IDS: readonly BuiltinThemeId[] = BUILTIN_THEMES.map((t) => t.id);
|
||||
export function isBuiltinTheme(value: unknown): value is BuiltinThemeId {
|
||||
return typeof value === "string" && (BUILTIN_THEME_IDS as readonly string[]).includes(value);
|
||||
}
|
||||
export function themeKind(id: BuiltinThemeId): "light" | "dark" {
|
||||
return BUILTIN_THEMES.find((t) => t.id === id)!.kind;
|
||||
}
|
||||
Reference in new issue
Заблокувати користувача