@@ -9,6 +9,7 @@ import type {
9
9
} from 'vue/compiler-sfc'
10
10
import type * as _compiler from 'vue/compiler-sfc'
11
11
import { computed , shallowRef } from 'vue'
12
+ import { exactRegex } from '@rolldown/pluginutils'
12
13
import { version } from '../package.json'
13
14
import { resolveCompiler } from './compiler'
14
15
import { parseVueRequest } from './utils/query'
@@ -162,7 +163,7 @@ export interface Options {
162
163
customElement ?: boolean | string | RegExp | ( string | RegExp ) [ ]
163
164
}
164
165
165
- export interface ResolvedOptions extends Options {
166
+ export interface ResolvedOptions extends Omit < Options , 'include' | 'exclude' > {
166
167
compiler : typeof _compiler
167
168
root : string
168
169
sourceMap : boolean
@@ -174,6 +175,14 @@ export interface ResolvedOptions extends Options {
174
175
export interface Api {
175
176
get options ( ) : ResolvedOptions
176
177
set options ( value : ResolvedOptions )
178
+
179
+ get include ( ) : string | RegExp | ( string | RegExp ) [ ] | undefined
180
+ /** include cannot be updated after `options` hook is called */
181
+ set include ( value : string | RegExp | ( string | RegExp ) [ ] | undefined )
182
+ get exclude ( ) : string | RegExp | ( string | RegExp ) [ ] | undefined
183
+ /** exclude cannot be updated after `options` hook is called */
184
+ set exclude ( value : string | RegExp | ( string | RegExp ) [ ] | undefined )
185
+
177
186
version : string
178
187
}
179
188
@@ -183,17 +192,19 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin<Api> {
183
192
const options = shallowRef < ResolvedOptions > ( {
184
193
isProduction : process . env . NODE_ENV === 'production' ,
185
194
compiler : null as any , // to be set in buildStart
186
- include : / \. v u e $ / ,
187
195
customElement : / \. c e \. v u e $ / ,
188
196
...rawOptions ,
189
197
root : process . cwd ( ) ,
190
198
sourceMap : true ,
191
199
cssDevSourcemap : false ,
192
200
} )
193
-
194
- const filter = computed ( ( ) =>
195
- createFilter ( options . value . include , options . value . exclude ) ,
201
+ const include = shallowRef < Exclude < Options [ 'include' ] , undefined > > (
202
+ rawOptions . include ?? / \. v u e $ / ,
196
203
)
204
+ const exclude = shallowRef < Options [ 'exclude' ] > ( rawOptions . exclude )
205
+ let optionsHookIsCalled = false
206
+
207
+ const filter = computed ( ( ) => createFilter ( include . value , exclude . value ) )
197
208
const customElementFilter = computed ( ( ) => {
198
209
const customElement =
199
210
options . value . features ?. customElement || options . value . customElement
@@ -204,7 +215,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin<Api> {
204
215
205
216
let transformCachedModule = false
206
217
207
- return {
218
+ const plugin : Plugin < Api > = {
208
219
name : 'vite:vue' ,
209
220
210
221
api : {
@@ -214,6 +225,28 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin<Api> {
214
225
set options ( value ) {
215
226
options . value = value
216
227
} ,
228
+ get include ( ) {
229
+ return include . value
230
+ } ,
231
+ set include ( value ) {
232
+ if ( optionsHookIsCalled ) {
233
+ throw new Error (
234
+ 'include cannot be updated after `options` hook is called' ,
235
+ )
236
+ }
237
+ include . value = value
238
+ } ,
239
+ get exclude ( ) {
240
+ return exclude . value
241
+ } ,
242
+ set exclude ( value ) {
243
+ if ( optionsHookIsCalled ) {
244
+ throw new Error (
245
+ 'exclude cannot be updated after `options` hook is called' ,
246
+ )
247
+ }
248
+ exclude . value = value
249
+ } ,
217
250
version,
218
251
} ,
219
252
@@ -317,6 +350,20 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin<Api> {
317
350
config . build . watch != null
318
351
} ,
319
352
353
+ options ( ) {
354
+ type TransformObjectHook = Extract <
355
+ typeof plugin . transform ,
356
+ { filter ?: unknown }
357
+ >
358
+ optionsHookIsCalled = true
359
+ ; ( plugin . transform as TransformObjectHook ) . filter = {
360
+ id : {
361
+ include : [ ...ensureArray ( include . value ) , / [ ? & ] v u e \b / ] ,
362
+ exclude : exclude . value ,
363
+ } ,
364
+ }
365
+ } ,
366
+
320
367
shouldTransformCachedModule ( { id } ) {
321
368
if ( transformCachedModule && parseVueRequest ( id ) . query . vue ) {
322
369
return true
@@ -338,110 +385,128 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin<Api> {
338
385
}
339
386
} ,
340
387
341
- async resolveId ( id ) {
342
- // component export helper
343
- if ( id === EXPORT_HELPER_ID ) {
344
- return id
345
- }
346
- // serve sub-part requests (*?vue) as virtual modules
347
- if ( parseVueRequest ( id ) . query . vue ) {
348
- return id
349
- }
388
+ resolveId : {
389
+ filter : {
390
+ id : [ exactRegex ( EXPORT_HELPER_ID ) , / [ ? & ] v u e \b / ] ,
391
+ } ,
392
+ handler ( id ) {
393
+ // component export helper
394
+ if ( id === EXPORT_HELPER_ID ) {
395
+ return id
396
+ }
397
+ // serve sub-part requests (*?vue) as virtual modules
398
+ if ( parseVueRequest ( id ) . query . vue ) {
399
+ return id
400
+ }
401
+ } ,
350
402
} ,
351
403
352
- load ( id , opt ) {
353
- if ( id === EXPORT_HELPER_ID ) {
354
- return helperCode
355
- }
404
+ load : {
405
+ filter : {
406
+ id : [ exactRegex ( EXPORT_HELPER_ID ) , / [ ? & ] v u e \b / ] ,
407
+ } ,
408
+ handler ( id , opt ) {
409
+ if ( id === EXPORT_HELPER_ID ) {
410
+ return helperCode
411
+ }
356
412
357
- const ssr = opt ?. ssr === true
413
+ const ssr = opt ?. ssr === true
358
414
359
- const { filename, query } = parseVueRequest ( id )
415
+ const { filename, query } = parseVueRequest ( id )
360
416
361
- // select corresponding block for sub-part virtual modules
362
- if ( query . vue ) {
363
- if ( query . src ) {
364
- return fs . readFileSync ( filename , 'utf-8' )
365
- }
366
- const descriptor = getDescriptor ( filename , options . value ) !
367
- let block : SFCBlock | null | undefined
368
- if ( query . type === 'script' ) {
369
- // handle <script> + <script setup> merge via compileScript()
370
- block = resolveScript (
371
- descriptor ,
372
- options . value ,
373
- ssr ,
374
- customElementFilter . value ( filename ) ,
375
- )
376
- } else if ( query . type === 'template' ) {
377
- block = descriptor . template !
378
- } else if ( query . type === 'style' ) {
379
- block = descriptor . styles [ query . index ! ]
380
- } else if ( query . index != null ) {
381
- block = descriptor . customBlocks [ query . index ]
382
- }
383
- if ( block ) {
384
- return {
385
- code : block . content ,
386
- map : block . map as any ,
417
+ // select corresponding block for sub-part virtual modules
418
+ if ( query . vue ) {
419
+ if ( query . src ) {
420
+ return fs . readFileSync ( filename , 'utf-8' )
421
+ }
422
+ const descriptor = getDescriptor ( filename , options . value ) !
423
+ let block : SFCBlock | null | undefined
424
+ if ( query . type === 'script' ) {
425
+ // handle <script> + <script setup> merge via compileScript()
426
+ block = resolveScript (
427
+ descriptor ,
428
+ options . value ,
429
+ ssr ,
430
+ customElementFilter . value ( filename ) ,
431
+ )
432
+ } else if ( query . type === 'template' ) {
433
+ block = descriptor . template !
434
+ } else if ( query . type === 'style' ) {
435
+ block = descriptor . styles [ query . index ! ]
436
+ } else if ( query . index != null ) {
437
+ block = descriptor . customBlocks [ query . index ]
438
+ }
439
+ if ( block ) {
440
+ return {
441
+ code : block . content ,
442
+ map : block . map as any ,
443
+ }
387
444
}
388
445
}
389
- }
446
+ } ,
390
447
} ,
391
448
392
- transform ( code , id , opt ) {
393
- const ssr = opt ?. ssr === true
394
- const { filename, query } = parseVueRequest ( id )
449
+ transform : {
450
+ // filter is set in options() hook
451
+ handler ( code , id , opt ) {
452
+ const ssr = opt ?. ssr === true
453
+ const { filename, query } = parseVueRequest ( id )
395
454
396
- if ( query . raw || query . url ) {
397
- return
398
- }
399
-
400
- if ( ! filter . value ( filename ) && ! query . vue ) {
401
- return
402
- }
455
+ if ( query . raw || query . url ) {
456
+ return
457
+ }
403
458
404
- if ( ! query . vue ) {
405
- // main request
406
- return transformMain (
407
- code ,
408
- filename ,
409
- options . value ,
410
- this ,
411
- ssr ,
412
- customElementFilter . value ( filename ) ,
413
- )
414
- } else {
415
- // sub block request
416
- const descriptor : ExtendedSFCDescriptor = query . src
417
- ? getSrcDescriptor ( filename , query ) ||
418
- getTempSrcDescriptor ( filename , query )
419
- : getDescriptor ( filename , options . value ) !
420
-
421
- if ( query . src ) {
422
- this . addWatchFile ( filename )
459
+ if ( ! filter . value ( filename ) && ! query . vue ) {
460
+ return
423
461
}
424
462
425
- if ( query . type === 'template' ) {
426
- return transformTemplateAsModule (
463
+ if ( ! query . vue ) {
464
+ // main request
465
+ return transformMain (
427
466
code ,
428
- descriptor ,
467
+ filename ,
429
468
options . value ,
430
469
this ,
431
470
ssr ,
432
471
customElementFilter . value ( filename ) ,
433
472
)
434
- } else if ( query . type === 'style' ) {
435
- return transformStyle (
436
- code ,
437
- descriptor ,
438
- Number ( query . index || 0 ) ,
439
- options . value ,
440
- this ,
441
- filename ,
442
- )
473
+ } else {
474
+ // sub block request
475
+ const descriptor : ExtendedSFCDescriptor = query . src
476
+ ? getSrcDescriptor ( filename , query ) ||
477
+ getTempSrcDescriptor ( filename , query )
478
+ : getDescriptor ( filename , options . value ) !
479
+
480
+ if ( query . src ) {
481
+ this . addWatchFile ( filename )
482
+ }
483
+
484
+ if ( query . type === 'template' ) {
485
+ return transformTemplateAsModule (
486
+ code ,
487
+ descriptor ,
488
+ options . value ,
489
+ this ,
490
+ ssr ,
491
+ customElementFilter . value ( filename ) ,
492
+ )
493
+ } else if ( query . type === 'style' ) {
494
+ return transformStyle (
495
+ code ,
496
+ descriptor ,
497
+ Number ( query . index || 0 ) ,
498
+ options . value ,
499
+ this ,
500
+ filename ,
501
+ )
502
+ }
443
503
}
444
- }
504
+ } ,
445
505
} ,
446
506
}
507
+ return plugin
508
+ }
509
+
510
+ function ensureArray < T > ( value : T | T [ ] ) : T [ ] {
511
+ return Array . isArray ( value ) ? value : [ value ]
447
512
}
0 commit comments