@@ -12,6 +12,7 @@ import {
12
12
compileStyleAsync ,
13
13
compileTemplate ,
14
14
parse ,
15
+ compileScript ,
15
16
SFCBlock ,
16
17
SFCDescriptor ,
17
18
SFCTemplateCompileOptions ,
@@ -45,6 +46,10 @@ export interface Options {
45
46
preprocessStyles ?: boolean
46
47
47
48
// sfc template options
49
+ templatePreprocessOptions ?: Record <
50
+ string ,
51
+ SFCTemplateCompileOptions [ 'preprocessOptions' ]
52
+ >
48
53
compiler ?: SFCTemplateCompileOptions [ 'compiler' ]
49
54
compilerOptions ?: SFCTemplateCompileOptions [ 'compilerOptions' ]
50
55
transformAssetUrls ?: SFCTemplateCompileOptions [ 'transformAssetUrls' ]
@@ -127,7 +132,7 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
127
132
if ( block ) {
128
133
return {
129
134
code : block . content ,
130
- map : normalizeSourceMap ( block . map ) ,
135
+ map : normalizeSourceMap ( block . map , id ) ,
131
136
}
132
137
}
133
138
}
@@ -142,6 +147,10 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
142
147
if ( ! query . src && ! filter ( query . filename ) ) return null
143
148
const descriptor = getDescriptor ( query . filename )
144
149
const hasScoped = descriptor . styles . some ( ( s ) => s . scoped )
150
+ if ( query . src ) {
151
+ this . addWatchFile ( query . filename ) ;
152
+ }
153
+
145
154
if ( query . type === 'template' ) {
146
155
const compilerKey = query . compiler
147
156
let compiler = options . compiler
@@ -174,17 +183,26 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
174
183
175
184
debug ( `transform(${ id } )` )
176
185
const block = descriptor . template !
186
+ const preprocessLang = block . lang
187
+ const preprocessOptions =
188
+ preprocessLang &&
189
+ options . templatePreprocessOptions &&
190
+ options . templatePreprocessOptions [ preprocessLang ]
177
191
const result = compileTemplate ( {
178
192
filename : query . filename ,
179
193
source : code ,
180
194
inMap : query . src ? undefined : block . map ,
181
- preprocessLang : block . lang ,
195
+ preprocessLang,
196
+ preprocessOptions,
182
197
preprocessCustomRequire : options . preprocessCustomRequire ,
183
198
compiler,
184
199
ssr : isServer ,
185
200
compilerOptions : {
186
201
...compilerOptions ,
187
202
scopeId : hasScoped ? `data-v-${ query . id } ` : undefined ,
203
+ bindingMetadata : descriptor . script
204
+ ? descriptor . script . bindings
205
+ : undefined ,
188
206
} ,
189
207
transformAssetUrls : options . transformAssetUrls ,
190
208
} )
@@ -211,25 +229,53 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
211
229
212
230
return {
213
231
code : result . code ,
214
- map : normalizeSourceMap ( result . map ! ) ,
232
+ map : normalizeSourceMap ( result . map ! , id ) ,
215
233
}
216
234
} else if ( query . type === 'style' ) {
217
235
debug ( `transform(${ id } )` )
218
236
const block = descriptor . styles [ query . index ] !
237
+
238
+ let preprocessOptions = options . preprocessOptions || { }
239
+ const preprocessLang = ( options . preprocessStyles
240
+ ? block . lang
241
+ : undefined ) as SFCAsyncStyleCompileOptions [ 'preprocessLang' ]
242
+
243
+ if ( preprocessLang ) {
244
+ preprocessOptions =
245
+ preprocessOptions [ preprocessLang ] || preprocessOptions
246
+ // include node_modules for imports by default
247
+ switch ( preprocessLang ) {
248
+ case 'scss' :
249
+ case 'sass' :
250
+ preprocessOptions = {
251
+ includePaths : [ 'node_modules' ] ,
252
+ ...preprocessOptions ,
253
+ }
254
+ break
255
+ case 'less' :
256
+ case 'stylus' :
257
+ preprocessOptions = {
258
+ paths : [ 'node_modules' ] ,
259
+ ...preprocessOptions ,
260
+ }
261
+ }
262
+ } else {
263
+ preprocessOptions = { }
264
+ }
265
+
219
266
const result = await compileStyleAsync ( {
220
267
filename : query . filename ,
221
268
id : `data-v-${ query . id ! } ` ,
222
269
source : code ,
223
270
scoped : block . scoped ,
271
+ vars : ! ! block . vars ,
224
272
modules : ! ! block . module ,
225
273
postcssOptions : options . postcssOptions ,
226
274
postcssPlugins : options . postcssPlugins ,
227
275
modulesOptions : options . cssModulesOptions ,
228
- preprocessLang : options . preprocessStyles
229
- ? ( block . lang as any )
230
- : undefined ,
276
+ preprocessLang,
231
277
preprocessCustomRequire : options . preprocessCustomRequire ,
232
- preprocessOptions : options . preprocessOptions || { } ,
278
+ preprocessOptions,
233
279
} )
234
280
235
281
if ( result . errors . length ) {
@@ -250,7 +296,7 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
250
296
} else {
251
297
return {
252
298
code : result . code ,
253
- map : normalizeSourceMap ( result . map ! ) ,
299
+ map : normalizeSourceMap ( result . map ! , id ) ,
254
300
}
255
301
}
256
302
}
@@ -376,21 +422,14 @@ function getDescriptor(id: string) {
376
422
throw new Error ( `${ id } is not parsed yet` )
377
423
}
378
424
379
- function parseSFC (
380
- code : string ,
381
- id : string ,
382
- sourceRoot : string
383
- ) : { descriptor : SFCDescriptor ; errors : CompilerError [ ] } {
425
+ function parseSFC ( code : string , id : string , sourceRoot : string ) {
384
426
const { descriptor, errors } = parse ( code , {
385
427
sourceMap : true ,
386
428
filename : id ,
387
429
sourceRoot : sourceRoot ,
388
- pad : 'line' ,
389
430
} )
390
-
391
431
cache . set ( id , descriptor )
392
-
393
- return { descriptor, errors }
432
+ return { descriptor, errors : errors }
394
433
}
395
434
396
435
function transformVueSFC (
@@ -416,13 +455,17 @@ function transformVueSFC(
416
455
const id = hash ( isProduction ? shortFilePath + '\n' + code : shortFilePath )
417
456
// feature information
418
457
const hasScoped = descriptor . styles . some ( ( s ) => s . scoped )
419
- const templateImport = getTemplateCode (
420
- descriptor ,
421
- resourcePath ,
422
- id ,
423
- hasScoped ,
424
- isServer
425
- )
458
+
459
+ const templateImport = ! descriptor . template
460
+ ? ''
461
+ : getTemplateCode ( descriptor , resourcePath , id , hasScoped , isServer )
462
+
463
+ const renderReplace = ! descriptor . template
464
+ ? ''
465
+ : isServer
466
+ ? `script.ssrRender = ssrRender`
467
+ : `script.render = render`
468
+
426
469
const scriptImport = getScriptCode ( descriptor , resourcePath )
427
470
const stylesCode = getStyleCode (
428
471
descriptor ,
@@ -440,7 +483,7 @@ function transformVueSFC(
440
483
templateImport ,
441
484
stylesCode ,
442
485
customBlocksCode ,
443
- isServer ? `script.ssrRender = ssrRender` : `script.render = render` ,
486
+ renderReplace ,
444
487
]
445
488
if ( hasScoped ) {
446
489
output . push ( `script.__scopeId = ${ _ ( `data-v-${ id } ` ) } ` )
@@ -461,7 +504,8 @@ function getTemplateCode(
461
504
hasScoped : boolean ,
462
505
isServer : boolean
463
506
) {
464
- let templateImport = `const render = () => {}`
507
+ const renderFnName = isServer ? 'ssrRender' : 'render'
508
+ let templateImport = `const ${ renderFnName } = () => {}`
465
509
let templateRequest
466
510
if ( descriptor . template ) {
467
511
const src = descriptor . template . src || resourcePath
@@ -471,24 +515,28 @@ function getTemplateCode(
471
515
const attrsQuery = attrsToQuery ( descriptor . template . attrs )
472
516
const query = `?vue&type=template${ idQuery } ${ srcQuery } ${ scopedQuery } ${ attrsQuery } `
473
517
templateRequest = _ ( src + query )
474
- templateImport = `import { ${
475
- isServer ? 'ssrRender' : 'render'
476
- } } from ${ templateRequest } `
518
+ templateImport = `import { ${ renderFnName } } from ${ templateRequest } `
477
519
}
478
520
479
521
return templateImport
480
522
}
481
523
482
524
function getScriptCode ( descriptor : SFCDescriptor , resourcePath : string ) {
483
525
let scriptImport = `const script = {}`
484
- if ( descriptor . script ) {
485
- const src = descriptor . script . src || resourcePath
486
- const attrsQuery = attrsToQuery ( descriptor . script . attrs , 'js' )
487
- const srcQuery = descriptor . script . src ? `&src` : ``
488
- const query = `?vue&type=script${ srcQuery } ${ attrsQuery } `
489
- const scriptRequest = _ ( src + query )
490
- scriptImport =
491
- `import script from ${ scriptRequest } \n` + `export * from ${ scriptRequest } ` // support named exports
526
+ if ( descriptor . script || descriptor . scriptSetup ) {
527
+ if ( compileScript ) {
528
+ descriptor . script = compileScript ( descriptor )
529
+ }
530
+ if ( descriptor . script ) {
531
+ const src = descriptor . script . src || resourcePath
532
+ const attrsQuery = attrsToQuery ( descriptor . script . attrs , 'js' )
533
+ const srcQuery = descriptor . script . src ? `&src` : ``
534
+ const query = `?vue&type=script${ srcQuery } ${ attrsQuery } `
535
+ const scriptRequest = _ ( src + query )
536
+ scriptImport =
537
+ `import script from ${ scriptRequest } \n` +
538
+ `export * from ${ scriptRequest } ` // support named exports
539
+ }
492
540
}
493
541
return scriptImport
494
542
}
@@ -561,21 +609,33 @@ function getCustomBlock(
561
609
return code
562
610
}
563
611
564
- function createRollupError ( id : string , error : CompilerError ) : RollupError {
565
- return {
566
- id,
567
- plugin : 'vue' ,
568
- pluginCode : String ( error . code ) ,
569
- message : error . message ,
570
- frame : error . loc ! . source ,
571
- parserError : error ,
572
- loc : error . loc
573
- ? {
574
- file : id ,
575
- line : error . loc . start . line ,
576
- column : error . loc . start . column ,
577
- }
578
- : undefined ,
612
+ function createRollupError (
613
+ id : string ,
614
+ error : CompilerError | SyntaxError
615
+ ) : RollupError {
616
+ if ( 'code' in error ) {
617
+ return {
618
+ id,
619
+ plugin : 'vue' ,
620
+ pluginCode : String ( error . code ) ,
621
+ message : error . message ,
622
+ frame : error . loc ! . source ,
623
+ parserError : error ,
624
+ loc : error . loc
625
+ ? {
626
+ file : id ,
627
+ line : error . loc . start . line ,
628
+ column : error . loc . start . column ,
629
+ }
630
+ : undefined ,
631
+ }
632
+ } else {
633
+ return {
634
+ id,
635
+ plugin : 'vue' ,
636
+ message : error . message ,
637
+ parserError : error ,
638
+ }
579
639
}
580
640
}
581
641
@@ -612,9 +672,14 @@ function _(any: any) {
612
672
return JSON . stringify ( any )
613
673
}
614
674
615
- function normalizeSourceMap ( map : SFCTemplateCompileResults [ 'map' ] ) : any {
675
+ function normalizeSourceMap ( map : SFCTemplateCompileResults [ 'map' ] , id : string ) : any {
616
676
if ( ! map ) return null as any
617
677
678
+ if ( ! id . includes ( 'type=script' ) ) {
679
+ map . file = id ;
680
+ map . sources [ 0 ] = id ;
681
+ }
682
+
618
683
return {
619
684
...map ,
620
685
version : Number ( map . version ) ,
0 commit comments