diff --git a/rspack.config.ts b/rspack.config.ts
index 607b5a1e9..f47bd96b0 100644
--- a/rspack.config.ts
+++ b/rspack.config.ts
@@ -108,11 +108,6 @@ export default defineConfig({
},
],
},
- {
- type: "asset/source",
- test: /\.d\.ts$/,
- exclude: /node_modules/,
- },
{
type: "asset/source",
test: /\.tpl$/,
diff --git a/src/locales/ach-UG/translation.json b/src/locales/ach-UG/translation.json
index ec678a48b..d543170be 100644
--- a/src/locales/ach-UG/translation.json
+++ b/src/locales/ach-UG/translation.json
@@ -460,5 +460,16 @@
"all": "crwdns10812:0crwdne10812:0",
"normal-tabs": "crwdns10814:0crwdne10814:0",
"incognito-tabs": "crwdns10816:0crwdne10816:0"
- }
+ },
+ "editor_config": "crwdns10818:0crwdne10818:0",
+ "editor_config_description": "crwdns10820:0crwdne10820:0",
+ "editor_type_definition": "crwdns10822:0crwdne10822:0",
+ "editor_type_definition_description": "crwdns10824:0crwdne10824:0",
+ "eslint_rules_reset": "crwdns10826:0crwdne10826:0",
+ "eslint_rules_saved": "crwdns10828:0crwdne10828:0",
+ "editor_config_reset": "crwdns10830:0crwdne10830:0",
+ "editor_config_saved": "crwdns10832:0crwdne10832:0",
+ "editor_config_format_error": "crwdns10834:0crwdne10834:0",
+ "editor_type_definition_reset": "crwdns10836:0crwdne10836:0",
+ "editor_type_definition_saved": "crwdns10838:0crwdne10838:0"
}
\ No newline at end of file
diff --git a/src/locales/en-US/translation.json b/src/locales/en-US/translation.json
index 181fd38c0..47ed4b2a5 100644
--- a/src/locales/en-US/translation.json
+++ b/src/locales/en-US/translation.json
@@ -460,5 +460,16 @@
"all": "All",
"normal-tabs": "Normal tags",
"incognito-tabs": "Incognito tags"
- }
+ },
+ "editor_config": "Editor Configuration",
+ "editor_config_description": "You can refer to the compilerOptions in jsconfig.js for configuration",
+ "editor_type_definition": "Editor Type Definition",
+ "editor_type_definition_description": "You can customize your own type definitions, and the script editor will automatically load these type definitions",
+ "eslint_rules_reset": "ESLint Rules Reset",
+ "eslint_rules_saved": "ESLint Rules Saved",
+ "editor_config_reset": "Editor Configuration Reset",
+ "editor_config_saved": "Editor Configuration Saved",
+ "editor_config_format_error": "Editor Configuration Format Error",
+ "editor_type_definition_reset": "Editor Type Definition Reset",
+ "editor_type_definition_saved": "Editor Type Definition Saved"
}
\ No newline at end of file
diff --git a/src/locales/zh-CN/translation.json b/src/locales/zh-CN/translation.json
index 7c3c81f53..5aecb014a 100644
--- a/src/locales/zh-CN/translation.json
+++ b/src/locales/zh-CN/translation.json
@@ -460,5 +460,16 @@
"all": "所有标签",
"normal-tabs": "普通标签",
"incognito-tabs": "隐身标签"
- }
+ },
+ "editor_config": "",
+ "editor_config_description": "",
+ "editor_type_definition": "",
+ "editor_type_definition_description": "",
+ "eslint_rules_reset": "",
+ "eslint_rules_saved": "",
+ "editor_config_reset": "",
+ "editor_config_saved": "",
+ "editor_config_format_error": "",
+ "editor_type_definition_reset": "",
+ "editor_type_definition_saved": ""
}
\ No newline at end of file
diff --git a/src/pages/components/CodeEditor/index.tsx b/src/pages/components/CodeEditor/index.tsx
index f258dbe85..964f43920 100644
--- a/src/pages/components/CodeEditor/index.tsx
+++ b/src/pages/components/CodeEditor/index.tsx
@@ -1,7 +1,7 @@
-import { LinterWorker } from "@App/pkg/utils/monaco-editor";
import { editor, Range } from "monaco-editor";
import React, { useEffect, useImperativeHandle, useRef, useState } from "react";
import { globalCache, systemConfig } from "@App/pages/store/global";
+import { LinterWorker } from "@App/pkg/utils/monaco-editor";
type Props = {
className?: string;
diff --git a/src/pages/components/CustomTrans/index.tsx b/src/pages/components/CustomTrans/index.tsx
index 53c73f68b..c0d9c28cb 100644
--- a/src/pages/components/CustomTrans/index.tsx
+++ b/src/pages/components/CustomTrans/index.tsx
@@ -4,8 +4,9 @@ import { useTranslation } from "react-i18next";
// 因为i18n的Trans组件打包后出现问题,所以自己实现一个
export const CustomTrans: React.FC<{
+ className?: string;
i18nKey: string;
-}> = ({ i18nKey }) => {
+}> = ({ className, i18nKey }) => {
const { t } = useTranslation();
const children: (JSX.Element | string)[] = [];
let content = t(i18nKey);
@@ -39,7 +40,7 @@ export const CustomTrans: React.FC<{
}
}
- return
{children}
;
+ return {children}
;
};
export default CustomTrans;
diff --git a/src/pages/options/main.tsx b/src/pages/options/main.tsx
index ff8669784..068de478a 100644
--- a/src/pages/options/main.tsx
+++ b/src/pages/options/main.tsx
@@ -11,7 +11,7 @@ import "./index.css";
import LoggerCore from "@App/app/logger/core.ts";
import { LoggerDAO } from "@App/app/repo/logger.ts";
import DBWriter from "@App/app/logger/db_writer.ts";
-import registerEditor from "@App/pkg/utils/monaco-editor.ts";
+import registerEditor from "@App/pkg/utils/monaco-editor";
import storeSubscribe from "../store/subscribe.ts";
import migrate from "@App/app/migrate.ts";
diff --git a/src/pages/options/routes/Setting.tsx b/src/pages/options/routes/Setting.tsx
index d4ecfdafb..173e4cb48 100644
--- a/src/pages/options/routes/Setting.tsx
+++ b/src/pages/options/routes/Setting.tsx
@@ -14,6 +14,7 @@ import FileSystemFactory from "@Packages/filesystem/factory";
import FileSystemParams from "@App/pages/components/FileSystemParams";
import { blackListSelfCheck } from "@App/pkg/utils/match";
import { obtainBlackList } from "@App/pkg/utils/utils";
+import CustomTrans from "@App/pages/components/CustomTrans";
function Setting() {
const [syncDelete, setSyncDelete] = useState();
@@ -29,6 +30,8 @@ function Setting() {
const [updateDisableScript, setUpdateDisableScript] = useState(false);
const [silenceUpdateScript, setSilenceUpdateScript] = useState(false);
const [enableEslint, setEnableEslint] = useState(false);
+ const [editorConfig, setEditorConfig] = useState("");
+ const [editorTypeDefinition, setEditorTypeDefinition] = useState("");
const [eslintConfig, setEslintConfig] = useState("");
const [blacklist, setBlacklist] = useState("");
const [badgeNumberType, setBadgeNumberType] = useState<"none" | "run_count" | "script_count">("run_count");
@@ -67,6 +70,8 @@ function Setting() {
systemConfig.getBadgeBackgroundColor(),
systemConfig.getBadgeTextColor(),
systemConfig.getScriptMenuDisplayType(),
+ systemConfig.getEditorConfig(),
+ systemConfig.getEditorTypeDefinition(),
]).then(
([
cloudSync,
@@ -82,6 +87,8 @@ function Setting() {
badgeBackgroundColor,
badgeTextColor,
scriptMenuDisplayType,
+ editorConfig,
+ editorTypeDefinition,
]) => {
setSyncDelete(cloudSync.syncDelete);
setSyncScriptStatus(cloudSync.syncStatus);
@@ -100,6 +107,8 @@ function Setting() {
setBadgeBackgroundColor(badgeBackgroundColor);
setBadgeTextColor(badgeTextColor);
setScriptMenuDisplayType(scriptMenuDisplayType);
+ setEditorConfig(editorConfig);
+ setEditorTypeDefinition(editorTypeDefinition);
}
);
};
@@ -445,14 +454,19 @@ function Setting() {
onChange={(v) => {
setEslintConfig(v);
}}
- onBlur={(v) => {
+ onBlur={() => {
prettier
.format(eslintConfig, {
parser: "json",
plugins: [prettierPluginEstree, babel],
})
- .then(() => {
- systemConfig.setEslintConfig(v.target.value);
+ .then((value) => {
+ if (value === "") {
+ Message.success(t("eslint_rules_reset"));
+ } else {
+ Message.success(t("eslint_rules_saved"));
+ }
+ systemConfig.setEslintConfig(value);
})
.catch((e) => {
Message.error(`${t("eslint_config_format_error")}: ${JSON.stringify(Logger.E(e))}`);
@@ -461,6 +475,74 @@ function Setting() {
/>
)}
+
+
+ {t("editor_config")}
+
+
+
{
+ setEditorConfig(v);
+ }}
+ onBlur={() => {
+ prettier
+ .format(editorConfig, {
+ parser: "json",
+ plugins: [prettierPluginEstree, babel],
+ })
+ .then((value) => {
+ if (value === "") {
+ Message.success(t("editor_config_reset"));
+ } else {
+ Message.success(t("editor_config_saved"));
+ }
+ systemConfig.setEditorConfig(value);
+ })
+ .catch((e) => {
+ Message.error(`${t("editor_config_format_error")}: ${JSON.stringify(Logger.E(e))}`);
+ });
+ }}
+ />
+
+
+
+ {t("editor_type_definition")}
+
+
+
{
+ setEditorTypeDefinition(v);
+ }}
+ onBlur={() => {
+ if (editorTypeDefinition === "") {
+ Message.success(t("editor_type_definition_reset"));
+ } else {
+ Message.success(t("editor_type_definition_saved"));
+ }
+ systemConfig.setEditorTypeDefinition(editorTypeDefinition);
+ }}
+ />
+
diff --git a/src/pkg/config/config.ts b/src/pkg/config/config.ts
index f7ee367ec..db99bac4b 100644
--- a/src/pkg/config/config.ts
+++ b/src/pkg/config/config.ts
@@ -1,10 +1,11 @@
-import { Message } from "@arco-design/web-react";
import ChromeStorage from "./chrome_storage";
import { defaultConfig } from "../../../packages/eslint/linter-config";
+import { defaultConfig as editorDefaultConfig } from "@App/pkg/utils/monaco-editor/config";
import type { FileSystemType } from "@Packages/filesystem/factory";
import type { MessageQueue, TKeyValue } from "@Packages/message/message_queue";
import { changeLanguage, matchLanguage } from "@App/locales/locales";
import { ExtVersion } from "@App/app/const";
+import defaultTypeDefinition from "@App/template/scriptcat.d.tpl";
export const SystemConfigChange = "systemConfigChange";
@@ -186,16 +187,37 @@ export class SystemConfig {
setEslintConfig(v: string) {
if (v === "") {
this.set("eslint_config", undefined);
- Message.success("ESLint规则已重置");
return;
}
- try {
- JSON.parse(v);
- this.set("eslint_config", v);
- Message.success("ESLint规则已保存");
- } catch (err: any) {
- Message.error(err.toString());
+ JSON.parse(v);
+ return this.set("eslint_config", v);
+ }
+
+ getEditorConfig() {
+ return this.get("editor_config", editorDefaultConfig);
+ }
+
+ setEditorConfig(v: string) {
+ if (v === "") {
+ this.set("editor_config", undefined);
+ return;
+ }
+ JSON.parse(v);
+ return this.set("editor_config", v);
+ }
+
+ // 获取typescript类型定义
+ getEditorTypeDefinition() {
+ return localStorage.getItem("editor_type_definition") || defaultTypeDefinition;
+ }
+
+ // 由于内容过大,只能存储到localStorage中
+ setEditorTypeDefinition(v: string) {
+ if (v === "") {
+ delete localStorage["editor_type_definition"];
+ return;
}
+ localStorage.setItem("editor_type_definition", v);
}
// 日志清理周期
diff --git a/src/pkg/utils/monaco-editor/config.ts b/src/pkg/utils/monaco-editor/config.ts
new file mode 100644
index 000000000..4db488342
--- /dev/null
+++ b/src/pkg/utils/monaco-editor/config.ts
@@ -0,0 +1,9 @@
+import type { languages } from "monaco-editor";
+
+const config = {
+ noSemanticValidation: true,
+ noSyntaxValidation: false,
+ onlyVisible: false,
+} as languages.typescript.CompilerOptions;
+
+export const defaultConfig = JSON.stringify(config, null, 2);
diff --git a/src/pkg/utils/monaco-editor.ts b/src/pkg/utils/monaco-editor/index.ts
similarity index 67%
rename from src/pkg/utils/monaco-editor.ts
rename to src/pkg/utils/monaco-editor/index.ts
index 821ebffbb..f304435a2 100644
--- a/src/pkg/utils/monaco-editor.ts
+++ b/src/pkg/utils/monaco-editor/index.ts
@@ -1,5 +1,4 @@
-import { globalCache } from "@App/pages/store/global";
-import dts from "@App/template/scriptcat.d.tpl";
+import { globalCache, systemConfig } from "@App/pages/store/global";
import EventEmitter from "eventemitter3";
import { languages } from "monaco-editor";
@@ -16,8 +15,6 @@ export default function registerEditor() {
},
};
- languages.typescript.javascriptDefaults.addExtraLib(dts, "scriptcat.d.ts");
-
// 悬停提示
const prompt: { [key: string]: any } = {
name: "脚本名称",
@@ -92,6 +89,53 @@ export default function registerEditor() {
isPreferred: true,
});
}
+ // 添加eslint-disable-next-line和eslint-disable
+ actions.push({
+ title: `添加 eslint-disable-next-line 注释`,
+ diagnostics: [val],
+ kind: "quickfix",
+ edit: {
+ edits: [
+ {
+ resource: model.uri,
+ textEdit: {
+ range: {
+ startLineNumber: val.startLineNumber,
+ endLineNumber: val.startLineNumber,
+ startColumn: 1,
+ endColumn: 1,
+ },
+ text: `// eslint-disable-next-line ${typeof val.code === "string" ? val.code : val.code!.value}\n`,
+ },
+ versionId: undefined,
+ },
+ ],
+ },
+ isPreferred: true,
+ });
+ actions.push({
+ title: `添加 eslint-disable 注释`,
+ diagnostics: [val],
+ kind: "quickfix",
+ edit: {
+ edits: [
+ {
+ resource: model.uri,
+ textEdit: {
+ range: {
+ startLineNumber: 1,
+ endLineNumber: 1,
+ startColumn: 1,
+ endColumn: 1,
+ },
+ text: `/* eslint-disable ${typeof val.code === "string" ? val.code : val.code!.value} */\n`,
+ },
+ versionId: undefined,
+ },
+ ],
+ },
+ isPreferred: true,
+ });
}
// const actions = context.markers.map((error) => {
@@ -119,6 +163,17 @@ export default function registerEditor() {
};
},
});
+
+ Promise.all([systemConfig.getEditorConfig(), systemConfig.getEditorTypeDefinition()]).then(
+ ([editorConfig, typeDefinition]) => {
+ // 设置编辑器设置
+ languages.typescript.javascriptDefaults.setCompilerOptions(
+ JSON.parse(editorConfig) as languages.typescript.CompilerOptions
+ );
+ // 注册类型定义
+ languages.typescript.javascriptDefaults.addExtraLib(typeDefinition, "scriptcat.d.ts");
+ }
+ );
}
export class LinterWorker {
diff --git a/vitest.config.ts b/vitest.config.ts
index 5172fa4d3..80250fbf1 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -1,4 +1,5 @@
import path from "path";
+import fs from "fs";
import { defineConfig } from "vitest/config";
export default defineConfig({
@@ -10,6 +11,18 @@ export default defineConfig({
"monaco-editor": path.resolve(__dirname, "./tests/mocks/monaco-editor.ts"),
},
},
+ plugins: [
+ {
+ name: "handle-tpl-files",
+ load(id) {
+ if (id.endsWith(".tpl")) {
+ // Return the content as a string asset
+ const content = fs.readFileSync(id, "utf-8");
+ return `export default ${JSON.stringify(content)};`;
+ }
+ },
+ },
+ ],
test: {
environment: "jsdom",
// List setup file