11import type { Project , Event } from '@alilc/lowcode-shell' ;
2- import { skeleton , common } from '@alilc/lowcode-engine' ;
2+ import { IPublicTypeProjectSchema } from '@alilc/lowcode-types' ;
3+ import { skeleton } from '@alilc/lowcode-engine' ;
34import {
45 beautifyCSS ,
56 compatGetSourceCodeMap ,
7+ fileMapToTree ,
68 getConstructorContent ,
79 getDefaultDeclaration ,
810 getInitFuncContent ,
911 lintIndex ,
1012 treeToMap ,
1113} from './utils' ;
1214import { FunctionEventParams , Monaco , ObjectType } from './types' ;
13- import type { editor } from 'monaco-editor' ;
15+ import { common } from '@alilc/lowcode-engine' ;
16+ import { editor } from 'monaco-editor' ;
1417import {
1518 addFunction ,
1619 focusByFunctionName ,
@@ -21,13 +24,14 @@ import { EditorContextType } from './Context';
2124import { Message } from '@alifd/next' ;
2225import { getMethods } from './utils/get-methods' ;
2326import { EditorHook , HookKeys } from './EditorHook' ;
24- import { Service } from './Service' ;
27+ import { PluginHooks , Service } from './Service' ;
28+ import { MonacoSuggestions } from './MonacoSuggestions' ;
2529
2630export * from './EditorHook' ;
2731
2832export interface EditorControllerState {
2933 declarationsMap : Record < string , string > ;
30- extraLibs : Array < { path : string ; content : string } > ;
34+ extraLibs : { path : string ; content : string } [ ] ;
3135}
3236
3337export type HookHandleFn < T = any > = ( fn : T ) => ( ) => void ;
@@ -49,7 +53,9 @@ export class EditorController extends EditorHook {
4953
5054 defaultFiles : ObjectType < string > ;
5155
52- monaco ?: Monaco ;
56+ useLess ?: boolean ;
57+
58+ public monaco ?: Monaco ;
5359
5460 private codeTemp ?: CodeTemp ;
5561
@@ -59,23 +65,30 @@ export class EditorController extends EditorHook {
5965
6066 private state : EditorControllerState ;
6167
62- codeEditor ?: editor . IStandaloneCodeEditor ;
68+ public codeEditor ?: editor . IStandaloneCodeEditor ;
69+
70+ public codeEditorCtx ?: EditorContextType ;
71+
72+ public service ! : Service ;
6373
64- private codeEditorCtx ?: EditorContextType ;
74+ private loadMonacoPromise ?: Promise < any > ;
6575
66- service ! : Service ;
76+ private monacoSuggestions : MonacoSuggestions ;
6777
68- onImportSchema : HookHandleFn < ( schema : any ) => void | Promise < void > > =
69- this . hookFactory ( HookKeys . onImport ) ;
78+ public onImportSchema : HookHandleFn <
79+ ( schema : IPublicTypeProjectSchema ) => void | Promise < void >
80+ > = this . hookFactory ( HookKeys . onImport ) ;
7081
71- onSourceCodeChange : HookHandleFn < ( code : any ) => void > = this . hookFactory (
72- HookKeys . onSourceCodeChange
73- ) ;
82+ public onSourceCodeChange : HookHandleFn < ( code : any ) => void > =
83+ this . hookFactory ( HookKeys . onSourceCodeChange ) ;
7484
75- onEditCodeChange : HookHandleFn <
85+ public onEditCodeChange : HookHandleFn <
7686 ( code : { content : string ; file : string } ) => void
7787 > = this . hookFactory ( HookKeys . onEditCodeChange ) ;
7888
89+ public onMonacoLoaded : HookHandleFn < ( monaco : Monaco ) => void > =
90+ this . hookFactory ( HookKeys . onMonacoLoaded ) ;
91+
7992 constructor ( ) {
8093 super ( ) ;
8194 this . state = {
@@ -85,6 +98,21 @@ export class EditorController extends EditorHook {
8598 this . listeners = [ ] ;
8699 this . defaultFiles = { } ;
87100 this . extraLibMap = new Map ( ) ;
101+ this . monacoSuggestions = new MonacoSuggestions ( this ) ;
102+ }
103+
104+ async initMonaco ( ) {
105+ if ( ! this . monaco ) {
106+ if ( ! this . loadMonacoPromise ) {
107+ const { getMonaco } = await import (
108+ '@alilc/lowcode-plugin-base-monaco-editor'
109+ ) ;
110+ this . loadMonacoPromise = getMonaco ( ) ;
111+ }
112+ this . monaco = await this . loadMonacoPromise ;
113+ this . triggerHook ( HookKeys . onMonacoLoaded , this . monaco ) ;
114+ this . service . triggerHook ( PluginHooks . onMonacoLoaded , this . monaco ) ;
115+ }
88116 }
89117
90118 init ( project : Project , editor : Event , service : Service ) {
@@ -94,6 +122,7 @@ export class EditorController extends EditorHook {
94122 this . setupEventListeners ( ) ;
95123 this . initCodeTempBySchema ( this . getSchema ( true ) ) ;
96124 this . triggerHook ( HookKeys . onImport , this . getSchema ( true ) ) ;
125+ this . initMonaco ( ) ;
97126 }
98127
99128 initCodeEditor (
@@ -102,6 +131,7 @@ export class EditorController extends EditorHook {
102131 ) {
103132 this . codeEditor = codeEditor ;
104133 this . codeEditorCtx = ctx ;
134+ this . monacoSuggestions . init ( ) ;
105135 }
106136
107137 setCodeTemp ( code : any | ( ( old : CodeTemp ) => CodeTemp ) ) {
@@ -122,7 +152,7 @@ export class EditorController extends EditorHook {
122152 this . applyLibs ( ) ;
123153 }
124154
125- addComponentDeclarations ( list : Array < [ string , string ] > = [ ] ) {
155+ addComponentDeclarations ( list : [ string , string ] [ ] = [ ] ) {
126156 for ( const [ key , dec ] of list ) {
127157 this . state . declarationsMap [ key ] = dec ;
128158 }
@@ -131,7 +161,7 @@ export class EditorController extends EditorHook {
131161 }
132162
133163 private publishExtraLib ( ) {
134- const libs : Array < { path : string ; content : string } > = [ ] ;
164+ const libs : { path : string ; content : string } [ ] = [ ] ;
135165 this . extraLibMap . forEach ( ( content , path ) => libs . push ( { content, path } ) ) ;
136166 this . state . extraLibs = libs ;
137167 this . publish ( ) ;
@@ -151,10 +181,7 @@ export class EditorController extends EditorHook {
151181
152182 private async applyLibs ( ) {
153183 if ( ! this . monaco ) {
154- const { getMonaco } = await import (
155- '@alilc/lowcode-plugin-base-monaco-editor'
156- ) ;
157- this . monaco = await getMonaco ( undefined ) as any ;
184+ await this . initMonaco ( ) ;
158185 }
159186 const decStr = Object . keys ( this . state . declarationsMap ) . reduce (
160187 ( v , k ) => `${ v } \n${ k } : ${ this . state . declarationsMap [ k ] } ;\n` ,
@@ -173,7 +200,7 @@ export class EditorController extends EditorHook {
173200 } ) ;
174201 }
175202
176- getSchema ( pure ?: boolean ) : any {
203+ getSchema ( pure ?: boolean ) : IPublicTypeProjectSchema {
177204 const schema = this . project . exportSchema (
178205 common . designerCabin . TransformStage . Save
179206 ) ;
@@ -182,15 +209,21 @@ export class EditorController extends EditorHook {
182209 ? treeToMap ( this . codeEditorCtx . fileTree )
183210 : this . codeTemp ?. _sourceCodeMap . files ; // 获取最新的fileMap
184211 if ( fileMap && ! pure ) {
185- if ( ! this . compileSourceCode ( fileMap ) ) {
186- throw new Error ( '编译失败' ) ;
212+ try {
213+ if ( ! this . compileSourceCode ( fileMap ) ) {
214+ // 下面会导致整个页面挂掉,先作为弱依赖,给个提示
215+ throw new Error ( '编译失败' ) ;
216+ }
217+ Object . assign ( schema . componentsTree [ 0 ] , this . codeTemp ) ;
218+ } catch ( error ) {
219+ console . error ( error ) ;
220+ Message . error ( '源码编译失败,请返回修改' ) ;
187221 }
188- Object . assign ( schema . componentsTree [ 0 ] , this . codeTemp ) ;
189222 }
190223 return schema ;
191224 }
192225
193- importSchema ( schema : any ) {
226+ importSchema ( schema : IPublicTypeProjectSchema ) {
194227 this . project . importSchema ( schema ) ;
195228 this . initCodeTempBySchema ( schema ) ;
196229 this . triggerHook ( HookKeys . onImport , schema ) ;
@@ -217,23 +250,22 @@ export class EditorController extends EditorHook {
217250 } ;
218251 }
219252
220- initCodeTempBySchema ( schema : any ) {
253+ public initCodeTempBySchema ( schema : IPublicTypeProjectSchema ) {
221254 const componentSchema = schema . componentsTree [ 0 ] || { } ;
222- const { css, methods, state, lifeCycles } = componentSchema ;
255+ const { css, methods, state, lifeCycles } = componentSchema as any ;
223256 const codeMap = ( componentSchema as any ) . _sourceCodeMap ;
224257 const defaultFileMap = {
225258 ...this . defaultFiles ,
226- ...getDefaultFileList ( schema ) ,
259+ ...getDefaultFileList ( schema , this . useLess ) ,
227260 } ;
228- const compatMap = compatGetSourceCodeMap ( codeMap ) ;
261+ const compatMap = compatGetSourceCodeMap ( codeMap , defaultFileMap ) ;
229262 this . codeTemp = {
230263 css,
231264 methods,
232265 state,
233266 lifeCycles,
234267 _sourceCodeMap : {
235268 ...compatMap ,
236- files : defaultFileMap ,
237269 } ,
238270 } ;
239271 }
@@ -253,8 +285,8 @@ export class EditorController extends EditorHook {
253285 this . editor ?. on ( 'common:codeEditor.addFunction' , ( (
254286 params : FunctionEventParams
255287 ) => {
288+ this . codeEditorCtx ?. selectFile ( 'index.js' , [ ] ) ;
256289 setTimeout ( ( ) => {
257- this . codeEditorCtx ?. selectFile ( 'index.js' , [ ] ) ;
258290 if ( this . monaco && this . codeEditor ) {
259291 addFunction ( this . codeEditor , params , this . monaco ) ;
260292 }
@@ -306,7 +338,20 @@ export class EditorController extends EditorHook {
306338 pageNode . state = state ;
307339 pageNode . methods = methods ;
308340 pageNode . lifeCycles = lifeCycles ;
309- pageNode . css = beautifyCSS ( fileMap [ 'index.css' ] || '' , { } ) ;
341+ const lessContent = fileMap [ 'index.less' ] ;
342+ // 没有less文件,走之前的逻辑
343+ if ( ! lessContent ) {
344+ pageNode . css = beautifyCSS ( fileMap [ 'index.css' ] || '' , { } ) ;
345+ }
346+ if ( this . useLess && lessContent ) {
347+ window . less ?. render ( lessContent , { } , ( err : any , output : any ) => {
348+ if ( err ) {
349+ Message . error ( 'less 编译失败' ) ;
350+ console . error ( err ) ;
351+ }
352+ pageNode . css = output ?. css || '' ;
353+ } ) ;
354+ }
310355 if ( lifeCycles . constructor === { } . constructor ) {
311356 lifeCycles . constructor = {
312357 originalCode : 'function constructor() { }' ,
@@ -341,10 +386,25 @@ export class EditorController extends EditorHook {
341386 return true ;
342387 }
343388
344- resetSaveStatus ( ) {
389+ public resetSaveStatus ( ) {
345390 this . codeEditorCtx ?. updateState ( { modifiedKeys : [ ] } ) ;
346391 }
347392
393+ // 添加一堆文件
394+ public addFiles ( fileMap : ObjectType < string > ) {
395+ if ( ! Object . keys ( fileMap || { } ) . length || ! this . codeEditorCtx ?. fileTree ) {
396+ return ;
397+ }
398+ const subTree = fileMapToTree ( fileMap ) ;
399+ const { files, dirs } = subTree ;
400+ const newTree = { ...this . codeEditorCtx ?. fileTree } ;
401+ newTree . files ?. push ( ...files ) ;
402+ newTree . dirs ?. push ( ...dirs ) ;
403+ this . codeEditorCtx . updateState ( {
404+ fileTree : newTree ,
405+ } ) ;
406+ }
407+
348408 triggerHook ( key : HookKeys , ...args : any [ ] ) : void {
349409 super . triggerHook ( key , ...args ) ;
350410 }
0 commit comments