nonaco 后置加载

This commit is contained in:
cnwhy
2024-05-28 19:16:39 +08:00
parent f387276a0d
commit 296672bb8c
10 changed files with 268 additions and 68 deletions
+1
View File
@@ -0,0 +1 @@
VITE_MONACO_URL=/monaco-editor
+1
View File
@@ -0,0 +1 @@
VITE_MONACO_URL=//unpkg.com/monaco-editor@0.47.0
+16 -14
View File
@@ -1,14 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>GOST API Manage</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<link rel="manifest" href="/manifest.json">
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>GOST API Manage</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<link rel="manifest" href="/manifest.json">
<script src="%VITE_MONACO_URL%/min/vs/loader.js"></script>
<!-- <script src="//unpkg.com/monaco-editor@0.47.0/min/vs/loader.js"></script> -->
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
-1
View File
@@ -30,7 +30,6 @@
"qs": "^6.11.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-monaco-editor": "^0.54.0",
"uuid": "^9.0.1"
},
"devDependencies": {
+4 -5
View File
@@ -21,8 +21,7 @@ import {
useServerConfig,
} from "../uitls/server";
import { download, jsonFormat } from "../uitls";
import { MonacoEditor } from "../uitls/userMonacoWorker";
import Ctx from "../uitls/ctx";
import { CodeEditor } from "../uitls/useMonacoEdit";
import * as API from "../api";
import ListCard, { ProCard } from "../components/ListCard";
import ChainCard from "../components/ListCard/Chains";
@@ -291,17 +290,17 @@ const Manage = () => {
<Col span={24}>
<ProCard boxShadow title="All Config JSON">
{/* <pre>{jsonFormat(gostConfig!)}</pre> */}
<MonacoEditor
<CodeEditor
className={"g-boder"}
value={jsonFormat(gostConfig!)}
height={"500"}
height={500}
language="json"
options={{
// selectOnLineNumbers: true,
minimap: { enabled: false },
readOnly: true,
}}
></MonacoEditor>
></CodeEditor>
</ProCard>
</Col>
</Row>
+10 -12
View File
@@ -3,12 +3,11 @@ import ReactDOM from "react-dom/client";
import { Button, Dropdown, Form, FormInstance, Space } from "antd";
import { DownOutlined } from "@ant-design/icons";
import { jsonFormat, jsonStringFormat, jsonParse, jsonEdit } from "../../uitls";
import * as monaco from "monaco-editor";
import { MonacoEditor, getModel, model, modelUri } from "../../uitls/userMonacoWorker";
import { Template } from "../../templates";
// import { render } from "react-dom";
// import { useServerConfig } from "../../uitls/server";
import ModalForm, { ModalFormProps } from "../ModalForm";
import { CodeEditor } from "../../uitls/useMonacoEdit";
const template2menu: any = (template: Template) => {
const { children, ...other } = template;
@@ -180,21 +179,20 @@ const JsonForm: React.FC<JsonFromProps> = (props) => {
},
]}
>
<MonacoEditor
<CodeEditor
className={"g-boder"}
height={300}
language="json"
options={{
// selectOnLineNumbers: true,
minimap: { enabled: false },
// readOnly: readOnly,
// json 数据格式测试
// model: monaco.editor.createModel('', "json", modelUri)
// model: getModel('')
// model: model
}}
></MonacoEditor>
}} />
{/* <MonacoEditor
className={"g-boder"}
height={300}
language="json"
options={{
minimap: { enabled: false },
}} /> */}
</Form.Item>
</ModalForm>
</>
+4
View File
@@ -0,0 +1,4 @@
namespace globalThis {
const monacoIsReady: Promise<any>;
const monaco: any;
}
+194
View File
@@ -0,0 +1,194 @@
import React, { useEffect, useRef, useState } from "react";
import { useBindValue } from "./use";
import type * as Monaco from "monaco-editor";
import classnames from "classnames";
(function () {
const require = (window as any).require;
let monacoURL;
const MONACO_URL = import.meta.env.VITE_MONACO_URL || '/monaco-editor';
if(/^(http[s]:)?\/\//.test(MONACO_URL)){
monacoURL = MONACO_URL + '/min/vs'
}else{
const baseURL = new URL(import.meta.env.BASE_URL, location.href).href;
monacoURL = new URL(`${MONACO_URL}/min/vs`, baseURL).href;
}
// if(import.meta.env.PROD && import.meta.env.VITE_MONACO_URL){
// monacoURL = import.meta.env.VITE_MONACO_URL + '/min/vs';
// }else{
// const baseURL = new URL(import.meta.env.BASE_URL, location.href).href;
// monacoURL = new URL("./monaco-editor/min/vs", baseURL).href;
// }
// console.log(`import_meta_env_BASE_URL`, import.meta.env.BASE_URL);
// console.log("baseURL", baseURL);
// const monacoURL = `//unpkg.com/monaco-editor@0.47.0/min/vs`
require.config({ paths: { vs: `${monacoURL}` } });
require.config({
"vs/nls": {
availableLanguages: {
"*": "zh-cn",
},
},
});
(window as any).monacoIsReady = new Promise((resolve, reject) => {
require(["vs/editor/editor.main"], function () {
resolve(monaco);
});
});
})();
monacoIsReady.then(() => {
// monacoPython.register(); //注册 关键字,内置函数 代码提示 ;
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
allowComments: true,
trailingCommas: "warning",
validate: true,
});
// monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
});
type CodeEditorProps = {
className?: string;
style?: React.CSSProperties;
language?: string;
value?: string;
theme?: string;
height?: string | number;
defaultValue?: string;
onChange?: (value: string) => void;
options?: Monaco.editor.IStandaloneEditorConstructionOptions;
};
const defOptions: Monaco.editor.IStandaloneEditorConstructionOptions = {
minimap: { enabled: false },
automaticLayout: true,
};
const CodeEditor_: React.ForwardRefRenderFunction<
Monaco.editor.IStandaloneCodeEditor,
CodeEditorProps
> = (props, ref) => {
const { onChange, options, height, className, theme = "vs", style } = props;
const [language, setLanguage] = useBindValue(props.language, "javascript");
const [value, setValue] = useBindValue(props.value, props.defaultValue, "");
const [isReady, setReady] = useState(false);
const divEl = useRef<HTMLDivElement>(null);
const editor = useRef<any>(null);
const self = useRef<any>({});
React.useImperativeHandle(ref, () => {
return editor.current!;
});
React.useImperativeHandle(
self,
() => {
return {
onChange,
};
},
[onChange]
);
useEffect(() => {
// let editor: any;
if (divEl.current) {
const el = divEl.current;
let _editor: Monaco.editor.IStandaloneCodeEditor;
monacoIsReady.then(() => {
_editor = editor.current = monaco.editor.create(el, {
value: value,
language: language,
theme,
...defOptions,
...options,
});
console.log("editor.current", editor.current.getDomNode());
_editor.onDidChangeModelContent(function (event: any) {
const _value = _editor.getValue();
setValue(_value);
self.current?.onChange?.(_value);
});
_editor.addCommand(monaco.KeyMod.Alt | monaco.KeyCode.KeyX, (e) => {
_editor.getAction("my-autoWrap-toggle")?.run();
});
_editor.addAction({
id: "my-autoWrap-toggle",
label: "切换自动换行",
keybindings: [
monaco.KeyMod.Alt | monaco.KeyCode.KeyZ,
// monaco.KeyMod.chord(
// monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK,
// monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyM
// ),
],
// A precondition for this action.
// precondition: null,
// A rule to evaluate on top of the precondition in order to dispatch the keybindings.
// keybindingContext: null,
// contextMenuGroupId: "navigation",
// contextMenuOrder: 1.5,
// Method that will be executed when the action is triggered.
// @param editor The editor instance is passed in as a convenience
run: function (ed, arg) {
// alert("i'm running => " + ed.getPosition());
// console.log("my-autoWrap-toggle", arg);
const workWrap = ed.getOption(monaco.editor.EditorOption.wordWrap);
ed.updateOptions({
wordWrap: workWrap === "on" ? "off" : "on",
});
},
});
setReady(true);
});
// let xc: any;
// const resizeObserver = new ResizeObserver((entries) => {
// // _editor?.layout();
// // console.log("resizeObserver");
// if (xc) clearTimeout(xc);
// xc = setTimeout(() => {
// _editor?.layout();
// }, 100);
// });
// resizeObserver.observe(el);
return () => {
_editor?.dispose?.();
// resizeObserver.unobserve(el);
// resizeObserver.disconnect();
};
}
}, []);
useEffect(() => {
if (editor.current) {
if (value != editor.current.getValue()) {
editor.current.setValue(value);
}
}
}, [value]);
return (
<div
className={classnames(className)}
style={{
height: height || "100%",
minHeight: 0,
minWidth: 0,
boxSizing: "border-box",
...style,
}}
ref={divEl}
></div>
);
};
export const CodeEditor = React.forwardRef(CodeEditor_);
@@ -1,8 +1,9 @@
/* eslint-disable */
import MonacoEditor from "react-monaco-editor";
// import { monaco } from "react-monaco-editor";
import * as monaco from "monaco-editor";
import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
import MonacoEditor from "react-monaco-editor";
// import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
// import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
// import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
@@ -31,46 +32,47 @@ self.MonacoEnvironment = {
},
};
var modelUri = monaco.Uri.parse("a://b/foo.json"); // a made up unique URI for our model
var getModel = (value: string) => {
return monaco.editor.createModel(value, "json", modelUri);
};
var model = getModel('');
// var modelUri = monaco.Uri.parse("a://b/foo.json"); // a made up unique URI for our model
// var getModel = (value: string) => {
// return monaco.editor.createModel(value, "json", modelUri);
// };
// var model = getModel("");
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
allowComments: true,
trailingCommas: "warning",
validate: true,
// json 数据格式测试
schemas: [
{
uri: "http://gost/config.json", // id of the first schema
fileMatch: [modelUri.toString()], // associate with our model
schema: {
type: "object",
properties: {
p1: {
enum: ["v1", "v2"],
},
p2: {
$ref: "http://myserver/bar-schema.json", // reference the second schema
},
},
},
},
{
uri: "http://myserver/bar-schema.json", // id of the second schema
schema: {
type: "object",
properties: {
q1: {
enum: ["x1", "x2"],
},
},
},
},
],
// schemas: [
// {
// uri: "http://gost/config.json", // id of the first schema
// fileMatch: [modelUri.toString()], // associate with our model
// schema: {
// type: "object",
// properties: {
// p1: {
// enum: ["v1", "v2"],
// },
// p2: {
// $ref: "http://myserver/bar-schema.json", // reference the second schema
// },
// },
// },
// },
// {
// uri: "http://myserver/bar-schema.json", // id of the second schema
// schema: {
// type: "object",
// properties: {
// q1: {
// enum: ["x1", "x2"],
// },
// },
// },
// },
// ],
});
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
export { MonacoEditor, modelUri, getModel, model };
export { MonacoEditor };
+1 -1
View File
@@ -21,7 +21,7 @@ export default defineConfig(({ command, mode }) => {
output: {
// manualChunks 配置
manualChunks: {
monaco: ["monaco-editor"],
// monaco: ["monaco-editor"],
antd: ["antd"],
},
},