@@ -41,11 +41,23 @@ export function emitFile(proj: project.Project, filePath: string): EmitOutput {
41
41
errors . push ( diagnosticToTSError ( diagnostic ) ) ;
42
42
} ) ;
43
43
44
- output . outputFiles . forEach ( o => {
45
- mkdirp . sync ( path . dirname ( o . name ) ) ;
46
- runExternalTranspiler ( o , proj ) ;
47
- fs . writeFileSync ( o . name , o . text , "utf8" ) ;
48
- } ) ;
44
+ {
45
+ let sourceMapContents : { [ index :string ] : any } = { } ;
46
+ output . outputFiles . forEach ( o => {
47
+ mkdirp . sync ( path . dirname ( o . name ) ) ;
48
+ let additionalEmits = runExternalTranspiler ( o , proj , sourceMapContents ) ;
49
+
50
+ if ( ! sourceMapContents [ o . name ] ) {
51
+ // .js.map files will be written as an "additional emit" later.
52
+ fs . writeFileSync ( o . name , o . text , "utf8" ) ;
53
+ }
54
+
55
+ additionalEmits . forEach ( a => {
56
+ mkdirp . sync ( path . dirname ( a . name ) ) ;
57
+ fs . writeFileSync ( a . name , a . text , "utf8" ) ;
58
+ } )
59
+ } ) ;
60
+ }
49
61
50
62
var outputFiles = output . outputFiles . map ( ( o ) => o . name ) ;
51
63
if ( path . extname ( filePath ) == '.d.ts' ) {
@@ -74,16 +86,89 @@ export function getRawOutput(proj: project.Project, filePath: string): ts.EmitOu
74
86
return output ;
75
87
}
76
88
77
- function runExternalTranspiler ( outputFile : ts . OutputFile , project : project . Project ) {
78
- var externalTranspiler = project . projectFile . project . externalTranspiler ;
89
+ function runExternalTranspiler ( outputFile : ts . OutputFile , project : project . Project , sourceMapContents : { [ index :string ] : any } ) : ts . OutputFile [ ] {
90
+ if ( ! isJSFile ( outputFile . name ) && ! isJSSourceMapFile ( outputFile . name ) ) {
91
+ return [ ] ;
92
+ }
93
+
94
+ let settings = project . projectFile . project ;
95
+ let externalTranspiler = settings . externalTranspiler ;
79
96
if ( ! externalTranspiler ) {
80
- return ;
97
+ return [ ] ;
98
+ }
99
+
100
+ if ( isJSSourceMapFile ( outputFile . name ) ) {
101
+ let sourceMapPayload = JSON . parse ( outputFile . text ) ;
102
+ let jsFileName = consistentPath ( path . resolve ( path . dirname ( outputFile . name ) , sourceMapPayload . file ) ) ;
103
+ sourceMapContents [ outputFile . name ] = { jsFileName : jsFileName , sourceMapPayload} ;
104
+ return [ ] ;
81
105
}
106
+
82
107
if ( externalTranspiler . toLocaleLowerCase ( ) === "babel" ) {
83
108
babel = require ( "babel" ) ;
84
- //TODO: pass relevant arguments from the project.
85
- //TODO: confirm source maps work as expected.
86
- outputFile . text = babel . transform ( outputFile . text , { } ) . code ;
109
+
110
+ let babelOptions : any = { } ;
111
+
112
+ let sourceMapFileName = getJSMapNameForJSFile ( outputFile . name ) ;
113
+
114
+ if ( sourceMapContents [ sourceMapFileName ] ) {
115
+ babelOptions . inputSourceMap = sourceMapContents [ sourceMapFileName ] . sourceMapPayload ;
116
+ }
117
+ if ( settings . compilerOptions . sourceMap ) {
118
+ babelOptions . sourceMaps = true ;
119
+ }
120
+ if ( settings . compilerOptions . inlineSourceMap ) {
121
+ babelOptions . sourceMaps = "inline" ;
122
+ }
123
+ if ( ! settings . compilerOptions . removeComments ) {
124
+ babelOptions . comments = true ;
125
+ }
126
+
127
+ let babelResult = babel . transform ( outputFile . text , babelOptions ) ;
128
+ outputFile . text = babelResult . code ;
129
+
130
+ if ( babelResult . map && settings . compilerOptions . sourceMap ) {
131
+ let additionalEmit : ts . OutputFile = {
132
+ name : sourceMapFileName ,
133
+ text : JSON . stringify ( babelResult . map ) ,
134
+ writeByteOrderMark : settings . compilerOptions . emitBOM
135
+ } ;
136
+
137
+ if ( additionalEmit . name === "" ) {
138
+ // can't emit a blank file name - this should only be reached if the TypeScript
139
+ // language service returns the .js file before the .js.map file.
140
+ console . warn ( `The TypeScript language service did not yet provide a .js.map name for file ${ outputFile . name } ` ) ;
141
+ return [ ] ;
142
+ }
143
+
144
+ return [ additionalEmit ] ;
145
+ }
146
+
147
+ return [ ] ;
148
+ }
149
+
150
+ function getJSMapNameForJSFile ( jsFileName : string ) {
151
+ for ( let jsMapName in sourceMapContents ) {
152
+ if ( sourceMapContents . hasOwnProperty ( jsMapName ) ) {
153
+ if ( sourceMapContents [ jsMapName ] . jsFileName === jsFileName ) {
154
+ return jsMapName ;
155
+ }
156
+ }
157
+ }
158
+ return "" ;
159
+ }
160
+ }
161
+
162
+
163
+
164
+ function isJSFile ( fileName : string ) {
165
+ return ( path . extname ( fileName ) . toLocaleLowerCase ( ) === ".js" ) ;
166
+ }
167
+
168
+ function isJSSourceMapFile ( fileName : string ) {
169
+ let lastExt = path . extname ( fileName ) ;
170
+ if ( lastExt === ".map" ) {
171
+ return isJSFile ( fileName . substr ( 0 , fileName . length - 4 ) ) ;
87
172
}
88
- return ;
173
+ return false ;
89
174
}
0 commit comments