Skip to content

Commit 43bf87f

Browse files
committed
fix: 冲突
2 parents ff7a035 + 36426d8 commit 43bf87f

File tree

13 files changed

+499
-116
lines changed

13 files changed

+499
-116
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @leoyuan @alvarto
66

77
/packages/plugin-manual/ @alvarto
8-
/packages/base-monaco-editor/ @alvarto
8+
/packages/base-monaco-editor/ @alvarto @wangshihao111
99
/packages/plugin-code-editor/ @alvarto
1010
/packages/plugin-schema/ @alvarto
1111
/packages/plugin-components-pane/ @mark-ck

packages/base-monaco-editor/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 1.1.0-beta.0
2+
3+
- 重构 type / path / value 联动,彻底修复 monaco 在多文件模式下覆盖多个 path 值的 bug
4+
- 修复 ts 类型问题 [@wangshihao111](https://github.com/wangshihao111)
5+
- 添加 configure 方法,支持配置是否开启 monaco 单例模式 [@wangshihao111](https://github.com/wangshihao111)
6+
- 新增插件参数:`enhancers`,用于强化编辑器功能 [@wangshihao111](https://github.com/wangshihao111)
7+
18
## 1.0.0
29

310
- Publish following changes

packages/base-monaco-editor/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alilc/lowcode-plugin-base-monaco-editor",
3-
"version": "1.0.0",
3+
"version": "1.1.0-beta.0",
44
"description": "代码编辑组件,monaco-editor 的低代码适配封装",
55
"publishConfig": {
66
"access": "public"
@@ -31,7 +31,7 @@
3131
"component"
3232
],
3333
"dependencies": {
34-
"@monaco-editor/loader": "^1.2.0",
34+
"@monaco-editor/loader": "1.3.0",
3535
"classnames": "^2.3.1"
3636
},
3737
"devDependencies": {
@@ -62,5 +62,5 @@
6262
"commit-msg": "f2elint commit-msg-scan"
6363
}
6464
},
65-
"homepage": "https://unpkg.com/@alilc/lowcode-plugin-base-monaco-editor@1.0.0/build/index.html"
65+
"homepage": "https://unpkg.com/@alilc/lowcode-plugin-base-monaco-editor@1.1.0-beta.0/build/index.html"
6666
}

packages/base-monaco-editor/src/helper.ts

Lines changed: 89 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,25 @@
11
/* eslint-disable no-empty */
2-
import { useEffect, useState, useRef, CSSProperties } from 'react';
3-
import loader from '@monaco-editor/loader';
2+
import React, { useEffect, useState, useRef, CSSProperties } from 'react';
3+
import { Monaco } from '@monaco-editor/loader';
4+
import type { editor as oEditor } from 'monaco-editor';
45
import { getMonaco } from './monaco';
56

6-
type IAmbigousFn = (...args: any[]) => any;
7-
87
// @todo fill type def for monaco editor without refering monaco editor
98
/**
109
* @see https://microsoft.github.io/monaco-editor/api/index.html
1110
*/
12-
export interface IEditorInstance {
13-
getModel: IAmbigousFn;
14-
dispose: IAmbigousFn;
15-
getValue: () => string;
16-
onDidChangeModelContent: (input: any) => void;
17-
setTheme: (input: string) => void;
18-
setModelLanguage: (model: any, language: string) => void;
19-
layout: () => void;
20-
setValue: (value: string) => void;
21-
executeEdits: IAmbigousFn;
22-
pushUndoStop: IAmbigousFn;
23-
EditorOption?: Record<string, any>;
24-
getOption?: (input: string) => any;
25-
onDidFocusEditorText: (...args: any[]) => void;
26-
onDidBlurEditorText: (...args: any[]) => void;
27-
getModifiedEditor?: () => IEditorInstance;
28-
setModel: IAmbigousFn;
29-
revealLineInCenter: IAmbigousFn;
30-
focus: IAmbigousFn;
31-
Range: new(...args: any[]) => any;
32-
getPosition: IAmbigousFn;
33-
setPosition: IAmbigousFn;
34-
deltaDecorations: IAmbigousFn;
35-
addAction: IAmbigousFn;
36-
saveViewState: () => ICodeEditorViewState;
37-
createModel: IAmbigousFn;
38-
[key: string]: any;
39-
}
40-
export interface IMonacoInstance {
41-
editor?: {
42-
create: IAmbigousFn;
43-
[key: string]: any;
44-
};
45-
KeyCode?: Record<string, any>;
46-
KeyMod?: Record<string, any>;
47-
[otherKeys: string]: any;
48-
}
11+
export type IEditorInstance = oEditor.IStandaloneCodeEditor | oEditor.IStandaloneDiffEditor;
4912

50-
interface ICodeEditorViewState {
51-
contributionsState: any;
52-
cursorState: any;
53-
viewState: any;
54-
}
13+
export type EditorEnhancer =
14+
(monaco: Monaco, editorIns: IEditorInstance) => any;
5515

5616
export interface IGeneralManacoEditorProps {
5717
/** [Monaco editor options](https://microsoft.github.io/monaco-editor/) */
5818
options?: Record<string, any>;
5919
/** callback after monaco's loaded and after editor's loaded */
60-
editorDidMount?: (monaco: IMonacoInstance, editor: IEditorInstance) => void;
20+
editorDidMount?: (monaco: Monaco, editor: IEditorInstance) => void;
6121
/** callback after monaco's loaded and before editor's loaded */
62-
editorWillMount?: (monaco: IMonacoInstance) => void;
22+
editorWillMount?: (monaco: Monaco) => void;
6323
/** path of the current model, useful when creating a multi-model editor */
6424
path?: string;
6525
/** whether to save the models' view states between model changes or not */
@@ -84,6 +44,7 @@ export interface IGeneralManacoEditorProps {
8444
enableOutline?: boolean;
8545
/** style of wrapper */
8646
style?: CSSProperties;
47+
enhancers?: EditorEnhancer[];
8748
}
8849

8950
export interface ISingleMonacoEditorProps extends IGeneralManacoEditorProps {
@@ -98,16 +59,15 @@ export interface IDiffMonacoEditorProps extends IGeneralManacoEditorProps {
9859
const CURRENT_LANGUAGE = ((window as any).locale || window.localStorage.getItem('vdev-locale') || '').replace(/_/, '-') || 'zh-CN';
9960
export const WORD_EDITOR_INITIALIZING = CURRENT_LANGUAGE === 'en-US' ? 'Initializing Editor' : '编辑器初始化中';
10061

101-
export const INITIAL_OPTIONS = {
62+
export const INITIAL_OPTIONS: oEditor.IStandaloneEditorConstructionOptions = {
10263
fontSize: 12,
10364
tabSize: 2,
10465
fontFamily: 'Menlo, Monaco, Courier New, monospace',
105-
renderIndentGuides: true,
10666
folding: true,
10767
minimap: {
10868
enabled: false,
10969
},
110-
autoIndent: true,
70+
autoIndent: 'advanced',
11171
contextmenu: true,
11272
useTabStops: true,
11373
wordBasedSuggestions: true,
@@ -126,9 +86,34 @@ export const INITIAL_OPTIONS = {
12686
},
12787
};
12888

129-
export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorProps) => {
89+
const DIFF_EDITOR_INITIAL_OPTIONS: oEditor.IStandaloneDiffEditorConstructionOptions = {
90+
fontSize: 12,
91+
fontFamily: 'Menlo, Monaco, Courier New, monospace',
92+
folding: true,
93+
minimap: {
94+
enabled: false,
95+
},
96+
autoIndent: 'advanced',
97+
contextmenu: true,
98+
useTabStops: true,
99+
formatOnPaste: true,
100+
automaticLayout: true,
101+
lineNumbers: 'on',
102+
wordWrap: 'off',
103+
scrollBeyondLastLine: false,
104+
fixedOverflowWidgets: false,
105+
snippetSuggestions: 'top',
106+
scrollbar: {
107+
vertical: 'auto',
108+
horizontal: 'auto',
109+
verticalScrollbarSize: 10,
110+
horizontalScrollbarSize: 10,
111+
},
112+
};
113+
114+
export const useEditor = <T = IEditorInstance>(type: 'single' | 'diff', props: IGeneralManacoEditorProps) => {
130115
const {
131-
editorDidMount, editorWillMount, theme, value, path, language, saveViewState, defaultValue,
116+
editorDidMount, editorWillMount, theme, value, path, language, saveViewState, defaultValue, enhancers,
132117
} = props;
133118

134119
const [isEditorReady, setIsEditorReady] = useState(false);
@@ -141,15 +126,21 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
141126
const previousPath = usePrevious(path);
142127
const requireConfigRef = useRef(props.requireConfig);
143128
const optionRef = useRef(props.options);
144-
const monacoRef = useRef<IMonacoInstance>();
129+
const monacoRef = useRef<Monaco>();
145130
const editorRef = useRef<IEditorInstance>();
146131
const containerRef = useRef<HTMLDivElement>();
147132
const typeRef = useRef(type);
148133
const editorDidMountRef = useRef<ISingleMonacoEditorProps['editorDidMount']>();
149134
const editorWillMountRef = useRef<ISingleMonacoEditorProps['editorWillMount']>();
150135

151136
const decomposeRef = useRef(false);
152-
const viewStatusRef = useRef<Map<any, ICodeEditorViewState>>(new Map());
137+
const viewStatusRef = useRef<Map<any, oEditor.ICodeEditorViewState>>(new Map());
138+
139+
const enhancersRef = useRef<any>({});
140+
141+
useEffect(() => {
142+
enhancersRef.current.enhancers = enhancers;
143+
}, [enhancers]);
153144

154145
useEffect(() => {
155146
editorDidMountRef.current = editorDidMount;
@@ -175,13 +166,8 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
175166
// make sure loader / editor only init once
176167
useEffect(() => {
177168
setLoading(true);
178-
179-
if (requireConfigRef.current) {
180-
loader.config(requireConfigRef.current);
181-
}
182-
183169
getMonaco(requireConfigRef.current)
184-
.then((monaco: any) => {
170+
.then((monaco: Monaco) => {
185171
// 兼容旧版本 monaco-editor 写死 MonacoEnvironment 的问题
186172
(window as any).MonacoEnvironment = undefined;
187173
if (typeof (window as any).define === 'function' && (window as any).define.amd) {
@@ -198,7 +184,7 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
198184
if (!containerRef.current) {
199185
return;
200186
}
201-
let editor: IEditorInstance;
187+
let editor: oEditor.IStandaloneCodeEditor | oEditor.IStandaloneDiffEditor;
202188
if (typeRef.current === 'single') {
203189
const model = getOrCreateModel(
204190
monaco,
@@ -223,14 +209,14 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
223209

224210
editor = monaco.editor.createDiffEditor(containerRef.current, {
225211
automaticLayout: true,
226-
...INITIAL_OPTIONS,
212+
...DIFF_EDITOR_INITIAL_OPTIONS,
227213
...optionRef.current,
228214
});
229215

230216
editor.setModel({ original: originalModel, modified: modifiedModel });
231217
}
232-
233218
editorRef.current = editor;
219+
enhancersRef.current.enhancers?.forEach((en: any) => en(monaco, editor as any));
234220
try {
235221
editorDidMountRef.current?.(monaco, editor);
236222
} catch (err) { }
@@ -253,39 +239,15 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
253239
monacoRef.current.editor.setTheme(theme);
254240
}, [isEditorReady, theme]);
255241

256-
// controlled value
257-
useEffect(() => {
258-
if (!isEditorReady) {
259-
return;
260-
}
261-
262-
const editor = type === 'diff'
263-
? editorRef.current.getModifiedEditor()
264-
: editorRef.current;
265-
266-
const nextValue = value ?? defaultValueRef.current ?? '';
267-
if (editor?.getOption?.(monacoRef.current?.editor.EditorOption.readOnly)) {
268-
editor?.setValue(nextValue);
269-
} else if (value !== editor?.getValue()) {
270-
editor?.executeEdits('', [{
271-
range: editor?.getModel().getFullModelRange(),
272-
text: nextValue,
273-
forceMoveMarkers: true,
274-
}]);
275-
276-
editor?.pushUndoStop();
277-
}
278-
}, [isEditorReady, type, value]);
279-
280242
// focus status
281243
useEffect(() => {
282244
if (!isEditorReady) {
283245
return;
284246
}
285247

286248
const editor = type === 'diff'
287-
? editorRef.current.getModifiedEditor()
288-
: editorRef.current;
249+
? (editorRef.current as oEditor.IStandaloneDiffEditor).getModifiedEditor()
250+
: editorRef.current as oEditor.IStandaloneCodeEditor;
289251
editor?.onDidFocusEditorText(() => {
290252
!decomposeRef.current && setFocused(true);
291253
});
@@ -301,7 +263,35 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
301263
};
302264
}, []);
303265

304-
// multi-model implementation
266+
// controlled value -- diff mode / without path only
267+
useEffect(() => {
268+
if (!isEditorReady) {
269+
return;
270+
}
271+
272+
if (type !== 'diff' && !!path) {
273+
return;
274+
}
275+
276+
const editor = type === 'diff'
277+
? (editorRef.current as oEditor.IStandaloneDiffEditor).getModifiedEditor()
278+
: editorRef.current as oEditor.IStandaloneCodeEditor;
279+
280+
const nextValue = value ?? defaultValueRef.current ?? '';
281+
if (editor?.getOption?.(monacoRef.current?.editor.EditorOption.readOnly)) {
282+
editor?.setValue(nextValue);
283+
} else if (value !== editor?.getValue()) {
284+
editor?.executeEdits('', [{
285+
range: editor?.getModel().getFullModelRange(),
286+
text: nextValue,
287+
forceMoveMarkers: true,
288+
}]);
289+
290+
editor?.pushUndoStop();
291+
}
292+
}, [isEditorReady, path, type, value]);
293+
294+
// multi-model && controlled value (shouldn't be diff mode)
305295
useEffect(() => {
306296
if (!isEditorReady) {
307297
return;
@@ -322,29 +312,30 @@ export const useEditor = (type: 'single' | 'diff', props: IGeneralManacoEditorPr
322312
path,
323313
);
324314

315+
const editor = editorRef.current as oEditor.IStandaloneCodeEditor;
325316
if (valueRef.current !== null && valueRef.current !== undefined && model.getValue() !== valueRef.current) {
326317
model.setValue(valueRef.current);
327318
}
328-
329319
if (model !== editorRef.current.getModel()) {
330-
saveViewState && viewStatusRef.current.set(previousPath, editorRef.current.saveViewState());
331-
editorRef.current.setModel(model);
332-
saveViewState && editorRef.current.restoreViewState(viewStatusRef.current.get(path));
320+
saveViewState && viewStatusRef.current.set(previousPath, editor.saveViewState());
321+
editor.setModel(model);
322+
saveViewState && editor.restoreViewState(viewStatusRef.current.get(path));
333323
}
334-
}, [isEditorReady, path, previousPath, type]);
324+
}, [isEditorReady, value, path, previousPath, type]);
335325

326+
let retEditorRef: React.MutableRefObject<T> = editorRef as any;
336327
return {
337328
isEditorReady,
338329
focused,
339330
loading,
340331
containerRef,
341332
monacoRef,
342-
editorRef,
333+
editorRef: retEditorRef,
343334
valueRef,
344335
} as const;
345336
};
346337

347-
function getOrCreateModel(monaco: IMonacoInstance, value?: string, language?: string, path?: string) {
338+
function getOrCreateModel(monaco: Monaco, value?: string, language?: string, path?: string) {
348339
if (path) {
349340
const prevModel = monaco
350341
.editor

0 commit comments

Comments
 (0)