1- import Editor , { type BeforeMount , type Monaco , type OnMount } from '@monaco-editor/react' ;
2- import type { editor } from 'monaco-editor' ;
1+ import Editor , { type Monaco , type OnMount } from '@monaco-editor/react' ;
2+ import type { editor } from 'tsover- monaco-editor' ;
33import { entries , filter , fromEntries , isTruthy , map , pipe } from 'remeda' ;
44import { SANDBOX_MODULES } from '../utils/examples/sandboxModules.ts' ;
55import type { ExampleCommonFile , ExampleSrcFile } from '../utils/examples/types.ts' ;
6- import { tsCompilerOptions } from '../utils/liveEditor/embeddedTypeScript.ts' ;
6+ import {
7+ tsnotoverCompilerOptions ,
8+ tsoverCompilerOptions ,
9+ } from '../utils/liveEditor/embeddedTypeScript.ts' ;
710
8- function handleEditorWillMount ( monaco : Monaco ) {
11+ // This setup is required for tsover to work, because monaco-react won't use custom monaco without `loader.config()`
12+ // Config docs: https://www.npmjs.com/package/@monaco -editor/react?activeTab=readme#loader-config
13+ // Integration docs: https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md
14+ import { loader } from '@monaco-editor/react' ;
15+ import * as monaco from 'tsover-monaco-editor' ;
16+ // oxlint-disable-next-line import/default
17+ import editorWorker from 'tsover-monaco-editor/esm/vs/editor/editor.worker?worker' ;
18+ // oxlint-disable-next-line import/default
19+ import jsonWorker from 'tsover-monaco-editor/esm/vs/language/json/json.worker?worker' ;
20+ // oxlint-disable-next-line import/default
21+ import cssWorker from 'tsover-monaco-editor/esm/vs/language/css/css.worker?worker' ;
22+ // oxlint-disable-next-line import/default
23+ import htmlWorker from 'tsover-monaco-editor/esm/vs/language/html/html.worker?worker' ;
24+ // oxlint-disable-next-line import/default
25+ import tsWorker from 'tsover-monaco-editor/esm/vs/language/typescript/ts.worker?worker' ;
26+
27+ self . MonacoEnvironment = {
28+ getWorker ( _ , label ) {
29+ switch ( label ) {
30+ case 'json' :
31+ return new jsonWorker ( ) ;
32+ case 'css' :
33+ return new cssWorker ( ) ;
34+ case 'html' :
35+ return new htmlWorker ( ) ;
36+ case 'typescript' :
37+ case 'javascript' :
38+ return new tsWorker ( ) ;
39+ default :
40+ return new editorWorker ( ) ;
41+ }
42+ } ,
43+ } ;
44+
45+ loader . config ( { monaco } ) ;
46+
47+ const handleEditorWillMount = ( tsover : boolean ) => ( monaco : Monaco ) => {
948 const tsDefaults = monaco ?. languages . typescript . typescriptDefaults ;
1049
1150 const reroutes = pipe (
@@ -34,10 +73,10 @@ function handleEditorWillMount(monaco: Monaco) {
3473 }
3574
3675 tsDefaults . setCompilerOptions ( {
37- ...tsCompilerOptions ,
76+ ...( tsover ? tsoverCompilerOptions : tsnotoverCompilerOptions ) ,
3877 paths : reroutes ,
3978 } ) ;
40- }
79+ } ;
4180
4281function handleEditorOnMount ( editor : editor . IStandaloneCodeEditor ) {
4382 // Folding regions in code automatically. Useful for code not strictly
@@ -46,45 +85,35 @@ function handleEditorOnMount(editor: editor.IStandaloneCodeEditor) {
4685}
4786
4887type Props = {
88+ language : 'typescript' | 'html' ;
89+ tsoverEnabled : boolean ;
4990 file : ExampleSrcFile | ExampleCommonFile ;
5091 shown : boolean ;
5192} ;
5293
53- const createCodeEditorComponent =
54- ( language : 'typescript' | 'html' , beforeMount ?: BeforeMount , onMount ?: OnMount ) =>
55- ( props : Props ) => {
56- const { file, shown } = props ;
57-
58- // Monaco needs relative paths to work correctly and '../../common/file.ts' will not do
59- const path =
60- 'common' in file
61- ? `common/${ file . path } `
62- : `${ file . exampleKey . replace ( '--' , '/' ) } /${ file . path } ` ;
63-
64- return (
65- < div className = { shown ? 'h-[calc(100%-7rem)] md:h-[calc(100%-3rem)]' : 'hidden' } >
66- < Editor
67- defaultLanguage = { language }
68- value = { file . tsnotoverContent ?? file . content }
69- path = { path }
70- beforeMount = { beforeMount }
71- onMount = { onMount }
72- options = { {
73- minimap : {
74- enabled : false ,
75- } ,
76- readOnly : true ,
77- domReadOnly : true ,
78- } }
79- />
80- </ div >
81- ) ;
82- } ;
94+ export function CodeEditor ( props : Props ) {
95+ const { language, tsoverEnabled, file, shown } = props ;
8396
84- export const TsCodeEditor = createCodeEditorComponent (
85- 'typescript' ,
86- handleEditorWillMount ,
87- handleEditorOnMount ,
88- ) ;
97+ // Monaco needs relative paths to work correctly and '../../common/file.ts' will not do
98+ const path =
99+ 'common' in file ? `common/${ file . path } ` : `${ file . exampleKey . replace ( '--' , '/' ) } /${ file . path } ` ;
89100
90- export const HtmlCodeEditor = createCodeEditorComponent ( 'html' ) ;
101+ return (
102+ < div className = { shown ? 'h-[calc(100%-7rem)] md:h-[calc(100%-3rem)]' : 'hidden' } >
103+ < Editor
104+ defaultLanguage = { language }
105+ value = { tsoverEnabled ? file . content : ( file . tsnotoverContent ?? file . content ) }
106+ path = { path }
107+ beforeMount = { language === 'typescript' ? handleEditorWillMount ( tsoverEnabled ) : undefined }
108+ onMount = { language === 'typescript' ? ( handleEditorOnMount as OnMount ) : undefined }
109+ options = { {
110+ minimap : {
111+ enabled : false ,
112+ } ,
113+ readOnly : true ,
114+ domReadOnly : true ,
115+ } }
116+ />
117+ </ div >
118+ ) ;
119+ }
0 commit comments