@@ -125,6 +125,9 @@ const CodeContainer = styled.div`
125125 }
126126` ;
127127
128+ const requireAMDModule = paths =>
129+ new Promise ( resolve => window . require ( paths , ( ) => resolve ( ) ) ) ;
130+
128131const handleError = (
129132 monaco ,
130133 editor ,
@@ -211,7 +214,7 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
211214 } ) ;
212215 } ;
213216
214- updateDecorations = ( classifications : Array < Object > ) => {
217+ updateDecorations = async ( classifications : Array < Object > ) => {
215218 const decorations = classifications . map ( classification => ( {
216219 range : new this . monaco . Range (
217220 classification . startLine ,
@@ -224,7 +227,7 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
224227 } ,
225228 } ) ) ;
226229
227- const modelInfo = this . getModelById ( this . props . id ) ;
230+ const modelInfo = await this . getModelById ( this . props . id ) ;
228231
229232 modelInfo . decorations = this . editor . deltaDecorations (
230233 modelInfo . decorations || [ ] ,
@@ -270,16 +273,16 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
270273 modelCache [ module . id ] . model . dispose ( ) ;
271274 delete modelCache [ module . id ] ;
272275
273- const newModel = this . createModel (
276+ this . createModel (
274277 module ,
275278 nextProps . modules ,
276279 nextProps . directories
277- ) ;
278-
279- if ( isCurrentlyOpened ) {
280- // Open it again if it was open
281- this . editor . setModel ( newModel ) ;
282- }
280+ ) . then ( newModel => {
281+ if ( isCurrentlyOpened ) {
282+ // Open it again if it was open
283+ this . editor . setModel ( newModel ) ;
284+ }
285+ } ) ;
283286 }
284287 }
285288 } ) ;
@@ -337,12 +340,12 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
337340 nextCode : ?string ,
338341 nextTitle : string ,
339342 } ) => {
340- if ( nextId !== currentId ) {
343+ if ( nextId !== currentId && this . editor ) {
341344 const pos = this . editor . getPosition ( ) ;
342345 if ( modelCache [ currentId ] ) {
343346 modelCache [ currentId ] . cursorPos = pos ;
344347 }
345- this.openNewModel(nextId, nextTitle);
348+ await this.openNewModel(nextId, nextTitle);
346349 this.editor.focus();
347350 }
348351 } ;
@@ -369,8 +372,9 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
369372 // Do in setTimeout, since disposeModules is async
370373 setTimeout ( ( ) => {
371374 // Initialize new models
372- this . initializeModules ( nextProps . modules ) ;
373- this . openNewModel ( nextId , nextTitle ) ;
375+ this . initializeModules ( nextProps . modules ) . then ( ( ) => {
376+ this . openNewModel ( nextId , nextTitle ) ;
377+ } ) ;
374378 } ) ;
375379 } else {
376380 this . swapDocuments ( {
@@ -411,7 +415,7 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
411415 this . editor . setPosition ( pos ) ;
412416 }
413417
414- getMode = (title: string) => {
418+ getMode = async (title: string) => {
415419 if ( title == null ) return 'javascript' ;
416420
417421 const kind = title . match ( / \. ( [ ^ . ] * ) $ / ) ;
@@ -425,7 +429,10 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
425429 } else if ( kind [ 1 ] === 'html' ) {
426430 return 'html' ;
427431 } else if ( kind [ 1 ] === 'vue' ) {
428- return 'html' ;
432+ if ( ! this . monaco . languages . getLanguages ( ) . find ( l => l . id === 'vue' ) ) {
433+ await requireAMDModule ( [ 'vs/language/vue/monaco.contribution' ] ) ;
434+ }
435+ return 'vue ';
429436 } else if ( kind [ 1 ] === 'less' ) {
430437 return 'less' ;
431438 } else if ( kind [ 1 ] === 'md' ) {
@@ -440,8 +447,8 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
440447 return 'typescript';
441448 } ;
442449
443- syntaxHighlight = ( code : string , title : string , version : string ) => {
444- const mode = this . getMode ( title ) ;
450+ syntaxHighlight = async ( code : string , title : string , version : string ) => {
451+ const mode = await this . getMode ( title ) ;
445452 if ( mode === 'typescript' || mode === 'javascript' ) {
446453 this . syntaxWorker . postMessage ( {
447454 code,
@@ -451,8 +458,9 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
451458 }
452459 } ;
453460
454- lint = ( code : string , title : string , version : string ) => {
455- if ( this . getMode ( title ) === 'javascript' ) {
461+ lint = async ( code : string , title : string , version : string ) => {
462+ const mode = await this . getMode ( title ) ;
463+ if ( mode === 'javascript' ) {
456464 this . lintWorker . postMessage ( {
457465 code,
458466 title,
@@ -461,7 +469,8 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
461469 }
462470 } ;
463471
464- handleChange = ( newCode : string ) => {
472+ handleChange = ( ) => {
473+ const newCode = this . editor . getModel ( ) . getValue ( ) ;
465474 this . props . changeCode ( this . props . id , newCode ) ;
466475
467476 this . syntaxHighlight (
@@ -484,7 +493,7 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
484493 } ) ;
485494 } ;
486495
487- configureEditor = (editor, monaco) => {
496+ configureEditor = async (editor, monaco) => {
488497 this . editor = editor ;
489498 this . monaco = monaco ;
490499
@@ -524,8 +533,8 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
524533 noSyntaxValidation : true ,
525534 } ) ;
526535
527- this . initializeModules ( ) ;
528- this . openNewModel ( this . props . id , this . props . title ) ;
536+ await this . initializeModules ( ) ;
537+ await this . openNewModel ( this . props . id , this . props . title ) ;
529538
530539 this . addKeyCommands ( ) ;
531540 enableEmmet ( editor , monaco , { } ) ;
@@ -565,6 +574,10 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
565574 } ) ;
566575 } ,
567576 } );
577+
578+ editor.onDidChangeModelContent(() => {
579+ this . handleChange ( ) ;
580+ } );
568581 } ;
569582
570583 closeFuzzySearch = ( ) => {
@@ -601,11 +614,8 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
601614 modelCache = { } ;
602615 } ;
603616
604- initializeModules = ( modules = this . props . modules ) => {
605- modules . forEach ( module => {
606- this . createModel ( module , modules ) ;
607- } ) ;
608- } ;
617+ initializeModules = ( modules = this . props . modules ) =>
618+ Promise . all ( modules . map ( module => this . createModel ( module , modules ) ) ) ;
609619
610620 resizeEditor = ( ) => {
611621 this . editor . layout ( ) ;
@@ -623,15 +633,15 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
623633 clearTimeout(this.sizeProbeInterval);
624634 }
625635
626- createModel = (
636+ createModel = async (
627637 module : Module ,
628638 modules : Array < Module > = this.props.modules,
629639 directories: Array< Directory > = this.props.directories
630640 ) => {
631641 // Remove the first slash, as this will otherwise create errors in monaco
632642 const path = getModulePath ( modules , directories , module . id ) ;
633643
634- const mode = this . getMode ( module . title ) ;
644+ const mode = await this . getMode ( module . title ) ;
635645 const model = this . monaco . editor . createModel (
636646 module . code ,
637647 mode === 'javascript' ? 'typescript' : mode ,
@@ -650,19 +660,19 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
650660 return model ;
651661 } ;
652662
653- getModelById = (id: string) => {
663+ getModelById = async (id: string) => {
654664 const { modules } = this.props;
655665 if (!modelCache[id]) {
656666 const module = modules . find ( m => m . id === id ) ;
657667
658- this . createModel ( module ) ;
668+ await this . createModel ( module ) ;
659669 }
660670
661671 return modelCache[id];
662672 } ;
663673
664- openNewModel = ( id : string , title : string ) => {
665- const modelInfo = this . getModelById ( id ) ;
674+ openNewModel = async ( id : string , title : string ) => {
675+ const modelInfo = await this . getModelById ( id ) ;
666676 this . editor . setModel ( modelInfo . model ) ;
667677
668678 if ( modelInfo . cursorPos ) {
@@ -789,12 +799,6 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
789799
790800 const options = this . getEditorOptions ( ) ;
791801
792- const requireConfig = {
793- url : '/public/vs/loader.js' ,
794- paths : {
795- vs : '/public/vs' ,
796- } ,
797- } ;
798802 return (
799803 < Container >
800804 < Header
@@ -815,13 +819,10 @@ export default class CodeEditor extends React.PureComponent<Props, State> {
815819 < MonacoEditor
816820 width = "100%"
817821 height = "100%"
818- language = "typescript"
819822 theme = "CodeSandbox"
820823 options = { options }
821- requireConfig = { requireConfig }
822824 editorDidMount = { this . configureEditor }
823825 editorWillMount = { this . editorWillMount }
824- onChange = { this . handleChange }
825826 openReference = { this . openReference }
826827 />
827828 </ CodeContainer >
0 commit comments