@@ -16,7 +16,9 @@ import babelRequest, { BabelResponse } from '../../utils/BabelRequest'
16
16
import { PaneOptions , containsPane } from '../../utils/Panes'
17
17
import { prefixObject , rowStyle } from '../../utils/Styles'
18
18
import { Tab } from '../../utils/Tab'
19
- import typeScriptRequest from '../../utils/TypeScriptRequest'
19
+ import typeScriptRequest , {
20
+ TypeScriptCompileRequest ,
21
+ } from '../../utils/TypeScriptRequest'
20
22
import { Props as EditorProps } from './Editor'
21
23
import ConsolePane from './panes/ConsolePane'
22
24
import EditorPane from './panes/EditorPane'
@@ -30,18 +32,20 @@ import {
30
32
WorkspaceStep ,
31
33
UserInterfaceStrings ,
32
34
CompilerOptions ,
35
+ TypeScriptOptions ,
33
36
} from '../../utils/options'
34
37
import { WorkspaceDiff } from './App'
35
38
import useRerenderEffect from '../../hooks/useRerenderEffect'
36
39
import type { ExternalModule } from '../player/VendorComponents'
40
+ import { basename , extname } from '../../utils/path'
37
41
38
42
const {
39
43
reducer,
40
44
actionCreators : {
41
45
compiled,
42
46
transpiled,
43
- babelCode ,
44
- babelError ,
47
+ compilerSuccess ,
48
+ compilerError ,
45
49
codeChange,
46
50
openEditorTab,
47
51
playerRun,
@@ -77,12 +81,6 @@ export interface PlaygroundOptions {
77
81
expandLevel ?: number
78
82
}
79
83
80
- export interface TypeScriptOptions {
81
- enabled ?: false
82
- libs ?: string [ ]
83
- types ?: string [ ]
84
- }
85
-
86
84
export interface ExternalStyles {
87
85
consolePane ?: CSSProperties
88
86
consoleRow ?: CSSProperties
@@ -385,37 +383,64 @@ export default function Workspace(props: Props) {
385
383
[ ]
386
384
)
387
385
388
- const updateStatus = ( filename : string , babelMessage : BabelResponse ) => {
389
- switch ( babelMessage . type ) {
390
- case 'code' :
391
- dispatch ( babelCode ( filename ) )
392
- break
393
- case 'error' :
394
- dispatch ( babelError ( filename , babelMessage . error . message ) )
395
- break
386
+ const updateStatus = ( filename : string , errorMessage ?: string ) => {
387
+ if ( errorMessage ) {
388
+ dispatch ( compilerError ( filename , errorMessage ) )
389
+ } else {
390
+ dispatch ( compilerSuccess ( filename ) )
396
391
}
397
392
}
398
393
399
- const compilerRequest = ( filename : string , code : string ) => {
400
- if ( props . compilerOptions . type === 'none' ) {
401
- dispatch ( compiled ( filename , code ) )
402
- } else {
403
- babelRequest ( {
394
+ const runBabel = useCallback ( ( filename : string , code : string ) => {
395
+ babelRequest ( {
396
+ filename,
397
+ code,
398
+ options : {
399
+ retainLines : true ,
400
+ maxLoopIterations : props . compilerOptions . maxLoopIterations ?? 0 ,
401
+ instrumentExpressionStatements :
402
+ props . playgroundOptions . instrumentExpressionStatements ,
403
+ } ,
404
+ } ) . then ( ( response : BabelResponse ) => {
405
+ updateStatus (
404
406
filename ,
405
- code,
406
- options : {
407
- retainLines : true ,
408
- maxLoopIterations : props . compilerOptions . maxLoopIterations ?? 0 ,
409
- instrumentExpressionStatements :
410
- props . playgroundOptions . instrumentExpressionStatements ,
411
- } ,
412
- } ) . then ( ( response : BabelResponse ) => {
413
- updateStatus ( filename , response )
414
-
415
- if ( response . type === 'code' ) {
416
- dispatch ( compiled ( response . filename , response . code ) )
417
- }
418
- } )
407
+ response . type === 'error' ? response . error . message : undefined
408
+ )
409
+
410
+ if ( response . type === 'code' ) {
411
+ dispatch ( compiled ( response . filename , response . code ) )
412
+ }
413
+ } )
414
+ } , [ ] )
415
+
416
+ // We currently ignore the output from tsc, instead transpiling the code
417
+ // again through babel. This is so the console.log/playground code transformations
418
+ // get applied. It could be worth rewriting them directly in tsc at some point.
419
+ const runTsc = useCallback ( ( filename : string , code : string ) => {
420
+ typeScriptRequest ( {
421
+ type : 'compile' ,
422
+ filename,
423
+ } ) . then ( ( response ) => {
424
+ if ( response . type === 'error' ) {
425
+ updateStatus ( filename , response . error . message )
426
+ return
427
+ }
428
+
429
+ runBabel ( filename , code )
430
+ } )
431
+ } , [ ] )
432
+
433
+ const compilerRequest = ( filename : string , code : string ) => {
434
+ switch ( props . compilerOptions . type ) {
435
+ case 'none' :
436
+ dispatch ( compiled ( filename , code ) )
437
+ break
438
+ case 'tsc' :
439
+ runTsc ( filename , code )
440
+ break
441
+ case 'babel' :
442
+ default :
443
+ runBabel ( filename , code )
419
444
}
420
445
}
421
446
@@ -440,26 +465,26 @@ export default function Workspace(props: Props) {
440
465
}
441
466
442
467
if ( typeof navigator !== 'undefined' ) {
468
+ if ( typescriptOptions . enabled ) {
469
+ typeScriptRequest ( {
470
+ type : 'init' ,
471
+ libs : typescriptOptions . libs || [ ] ,
472
+ types : typescriptOptions . types || [ ] ,
473
+ compilerOptions : typescriptOptions . compilerOptions || { } ,
474
+ } )
475
+
476
+ typeScriptRequest ( {
477
+ type : 'files' ,
478
+ files,
479
+ } )
480
+ }
481
+
443
482
// Cache and compile each file
444
483
Object . keys ( files ) . forEach ( ( filename ) => {
445
484
const code = files [ filename ]
446
485
447
486
state . codeCache [ filename ] = code
448
487
449
- if ( typescriptOptions . enabled ) {
450
- typeScriptRequest ( {
451
- type : 'libs' ,
452
- libs : typescriptOptions . libs || [ ] ,
453
- types : typescriptOptions . types || [ ] ,
454
- } )
455
-
456
- typeScriptRequest ( {
457
- type : 'file' ,
458
- filename,
459
- code,
460
- } )
461
- }
462
-
463
488
if ( playerVisible ) {
464
489
compilerRequest ( filename , code )
465
490
}
@@ -477,9 +502,8 @@ export default function Workspace(props: Props) {
477
502
( code : string ) => {
478
503
if ( typescriptOptions . enabled ) {
479
504
typeScriptRequest ( {
480
- type : 'file' ,
481
- filename : state . activeFile ,
482
- code,
505
+ type : 'files' ,
506
+ files : { [ state . activeFile ] : code } ,
483
507
} )
484
508
}
485
509
0 commit comments