1
1
import { dirname , isAbsolute , join } from 'path' ;
2
2
3
3
import ts from 'typescript' ;
4
+ import { compile } from 'svelte/compiler' ;
4
5
5
6
import { throwTypescriptError } from '../modules/errors' ;
7
+ import { createTagRegex , parseAttributes , stripTags } from '../modules/markup' ;
6
8
import type { Transformer , Options } from '../types' ;
7
9
8
10
type CompilerOptions = Options . Typescript [ 'compilerOptions' ] ;
@@ -53,6 +55,66 @@ const importTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
53
55
return ( node ) => ts . visitNode ( node , visit ) ;
54
56
} ;
55
57
58
+ function getComponentScriptContent ( markup : string ) : string {
59
+ const regex = createTagRegex ( 'script' , 'gi' ) ;
60
+ let match : RegExpMatchArray ;
61
+
62
+ while ( ( match = regex . exec ( markup ) ) !== null ) {
63
+ const { context } = parseAttributes ( match [ 1 ] ) ;
64
+
65
+ if ( context !== 'module' ) {
66
+ return match [ 2 ] ;
67
+ }
68
+ }
69
+
70
+ return '' ;
71
+ }
72
+
73
+ function injectVarsToCode ( {
74
+ content,
75
+ markup,
76
+ filename,
77
+ attributes,
78
+ } : {
79
+ content : string ;
80
+ markup ?: string ;
81
+ filename ?: string ;
82
+ attributes ?: Record < string , any > ;
83
+ } ) : string {
84
+ if ( ! markup ) return content ;
85
+
86
+ const { vars } = compile ( stripTags ( markup ) , {
87
+ generate : false ,
88
+ varsReport : 'full' ,
89
+ errorMode : 'warn' ,
90
+ filename,
91
+ } ) ;
92
+
93
+ const sep = '\nconst $$$$$$$$ = null;\n' ;
94
+ const varsValues = vars . map ( ( v ) => v . name ) . join ( ',' ) ;
95
+ const injectedVars = `const $$vars$$ = [${ varsValues } ];` ;
96
+
97
+ if ( attributes ?. context === 'module' ) {
98
+ const componentScript = getComponentScriptContent ( markup ) ;
99
+
100
+ return `${ content } ${ sep } ${ componentScript } \n${ injectedVars } ` ;
101
+ }
102
+
103
+ return `${ content } ${ sep } ${ injectedVars } ` ;
104
+ }
105
+
106
+ function stripInjectedCode ( {
107
+ compiledCode,
108
+ markup,
109
+ } : {
110
+ compiledCode : string ;
111
+ markup ?: string ;
112
+ } ) : string {
113
+ return markup
114
+ ? compiledCode . slice ( 0 , compiledCode . indexOf ( 'const $$$$$$$$ = null;' ) )
115
+ : compiledCode ;
116
+ }
117
+
56
118
export function loadTsconfig (
57
119
compilerOptionsJSON : any ,
58
120
filename : string ,
@@ -103,7 +165,9 @@ export function loadTsconfig(
103
165
const transformer : Transformer < Options . Typescript > = ( {
104
166
content,
105
167
filename,
168
+ markup,
106
169
options = { } ,
170
+ attributes,
107
171
} ) => {
108
172
// default options
109
173
const compilerOptionsJSON = {
@@ -140,17 +204,18 @@ const transformer: Transformer<Options.Typescript> = ({
140
204
}
141
205
142
206
const {
143
- outputText : code ,
207
+ outputText : compiledCode ,
144
208
sourceMapText : map ,
145
209
diagnostics,
146
- } = ts . transpileModule ( content , {
147
- fileName : filename ,
148
- compilerOptions,
149
- reportDiagnostics : options . reportDiagnostics !== false ,
150
- transformers : {
151
- before : [ importTransformer ] ,
210
+ } = ts . transpileModule (
211
+ injectVarsToCode ( { content, markup, filename, attributes } ) ,
212
+ {
213
+ fileName : filename ,
214
+ compilerOptions,
215
+ reportDiagnostics : options . reportDiagnostics !== false ,
216
+ transformers : markup ? { } : { before : [ importTransformer ] } ,
152
217
} ,
153
- } ) ;
218
+ ) ;
154
219
155
220
if ( diagnostics . length > 0 ) {
156
221
// could this be handled elsewhere?
@@ -167,6 +232,8 @@ const transformer: Transformer<Options.Typescript> = ({
167
232
}
168
233
}
169
234
235
+ const code = stripInjectedCode ( { compiledCode, markup } ) ;
236
+
170
237
return {
171
238
code,
172
239
map,
0 commit comments