@@ -49,122 +49,124 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
4949 return environment . config . consumer === 'client'
5050 } ,
5151
52- async transform ( code , id ) {
53- if (
54- id !== preloadHelperId &&
55- id !== CLIENT_ENTRY &&
56- code . includes ( 'new URL' ) &&
57- code . includes ( `import.meta.url` )
58- ) {
59- let s : MagicString | undefined
60- const assetImportMetaUrlRE =
61- / \b n e w \s + U R L \s * \( \s * ( ' [ ^ ' ] + ' | " [ ^ " ] + " | ` [ ^ ` ] + ` ) \s * , \s * i m p o r t \. m e t a \. u r l \s * (?: , \s * ) ? \) / dg
62- const cleanString = stripLiteral ( code )
52+ transform : {
53+ async handler ( code , id ) {
54+ if (
55+ id !== preloadHelperId &&
56+ id !== CLIENT_ENTRY &&
57+ code . includes ( 'new URL' ) &&
58+ code . includes ( `import.meta.url` )
59+ ) {
60+ let s : MagicString | undefined
61+ const assetImportMetaUrlRE =
62+ / \b n e w \s + U R L \s * \( \s * ( ' [ ^ ' ] + ' | " [ ^ " ] + " | ` [ ^ ` ] + ` ) \s * , \s * i m p o r t \. m e t a \. u r l \s * (?: , \s * ) ? \) / dg
63+ const cleanString = stripLiteral ( code )
6364
64- let match : RegExpExecArray | null
65- while ( ( match = assetImportMetaUrlRE . exec ( cleanString ) ) ) {
66- const [ [ startIndex , endIndex ] , [ urlStart , urlEnd ] ] = match . indices !
67- if ( hasViteIgnoreRE . test ( code . slice ( startIndex , urlStart ) ) ) continue
65+ let match : RegExpExecArray | null
66+ while ( ( match = assetImportMetaUrlRE . exec ( cleanString ) ) ) {
67+ const [ [ startIndex , endIndex ] , [ urlStart , urlEnd ] ] = match . indices !
68+ if ( hasViteIgnoreRE . test ( code . slice ( startIndex , urlStart ) ) ) continue
6869
69- const rawUrl = code . slice ( urlStart , urlEnd )
70+ const rawUrl = code . slice ( urlStart , urlEnd )
7071
71- if ( ! s ) s = new MagicString ( code )
72+ if ( ! s ) s = new MagicString ( code )
7273
73- // potential dynamic template string
74- if ( rawUrl [ 0 ] === '`' && rawUrl . includes ( '${' ) ) {
75- const queryDelimiterIndex = getQueryDelimiterIndex ( rawUrl )
76- const hasQueryDelimiter = queryDelimiterIndex !== - 1
77- const pureUrl = hasQueryDelimiter
78- ? rawUrl . slice ( 0 , queryDelimiterIndex ) + '`'
79- : rawUrl
80- const queryString = hasQueryDelimiter
81- ? rawUrl . slice ( queryDelimiterIndex , - 1 )
82- : ''
83- const ast = this . parse ( pureUrl )
84- const templateLiteral = ( ast as any ) . body [ 0 ] . expression
85- if ( templateLiteral . expressions . length ) {
86- const pattern = buildGlobPattern ( templateLiteral )
87- if ( pattern . startsWith ( '*' ) ) {
88- // don't transform for patterns like this
89- // because users won't intend to do that in most cases
74+ // potential dynamic template string
75+ if ( rawUrl [ 0 ] === '`' && rawUrl . includes ( '${' ) ) {
76+ const queryDelimiterIndex = getQueryDelimiterIndex ( rawUrl )
77+ const hasQueryDelimiter = queryDelimiterIndex !== - 1
78+ const pureUrl = hasQueryDelimiter
79+ ? rawUrl . slice ( 0 , queryDelimiterIndex ) + '`'
80+ : rawUrl
81+ const queryString = hasQueryDelimiter
82+ ? rawUrl . slice ( queryDelimiterIndex , - 1 )
83+ : ''
84+ const ast = this . parse ( pureUrl )
85+ const templateLiteral = ( ast as any ) . body [ 0 ] . expression
86+ if ( templateLiteral . expressions . length ) {
87+ const pattern = buildGlobPattern ( templateLiteral )
88+ if ( pattern . startsWith ( '*' ) ) {
89+ // don't transform for patterns like this
90+ // because users won't intend to do that in most cases
91+ continue
92+ }
93+
94+ const globOptions = {
95+ eager : true ,
96+ import : 'default' ,
97+ // A hack to allow 'as' & 'query' exist at the same time
98+ query : injectQuery ( queryString , 'url' ) ,
99+ }
100+ s . update (
101+ startIndex ,
102+ endIndex ,
103+ `new URL((import.meta.glob(${ JSON . stringify (
104+ pattern ,
105+ ) } , ${ JSON . stringify (
106+ globOptions ,
107+ ) } ))[${ pureUrl } ], import.meta.url)`,
108+ )
90109 continue
91110 }
111+ }
92112
93- const globOptions = {
94- eager : true ,
95- import : 'default' ,
96- // A hack to allow 'as' & 'query' exist at the same time
97- query : injectQuery ( queryString , 'url' ) ,
98- }
99- s . update (
100- startIndex ,
101- endIndex ,
102- `new URL((import.meta.glob(${ JSON . stringify (
103- pattern ,
104- ) } , ${ JSON . stringify (
105- globOptions ,
106- ) } ))[${ pureUrl } ], import.meta.url)`,
107- )
113+ const url = rawUrl . slice ( 1 , - 1 )
114+ if ( isDataUrl ( url ) ) {
108115 continue
109116 }
110- }
111-
112- const url = rawUrl . slice ( 1 , - 1 )
113- if ( isDataUrl ( url ) ) {
114- continue
115- }
116- let file : string | undefined
117- if ( url [ 0 ] === '.' ) {
118- file = slash ( path . resolve ( path . dirname ( id ) , url ) )
119- file = tryFsResolve ( file , fsResolveOptions ) ?? file
120- } else {
121- assetResolver ??= createBackCompatIdResolver ( config , {
122- extensions : [ ] ,
123- mainFields : [ ] ,
124- tryIndex : false ,
125- preferRelative : true ,
126- } )
127- file = await assetResolver ( this . environment , url , id )
128- file ??=
129- url [ 0 ] === '/'
130- ? slash ( path . join ( publicDir , url ) )
131- : slash ( path . resolve ( path . dirname ( id ) , url ) )
132- }
117+ let file : string | undefined
118+ if ( url [ 0 ] === '.' ) {
119+ file = slash ( path . resolve ( path . dirname ( id ) , url ) )
120+ file = tryFsResolve ( file , fsResolveOptions ) ?? file
121+ } else {
122+ assetResolver ??= createBackCompatIdResolver ( config , {
123+ extensions : [ ] ,
124+ mainFields : [ ] ,
125+ tryIndex : false ,
126+ preferRelative : true ,
127+ } )
128+ file = await assetResolver ( this . environment , url , id )
129+ file ??=
130+ url [ 0 ] === '/'
131+ ? slash ( path . join ( publicDir , url ) )
132+ : slash ( path . resolve ( path . dirname ( id ) , url ) )
133+ }
133134
134- // Get final asset URL. If the file does not exist,
135- // we fall back to the initial URL and let it resolve in runtime
136- let builtUrl : string | undefined
137- if ( file ) {
138- try {
139- if ( publicDir && isParentDirectory ( publicDir , file ) ) {
140- const publicPath = '/' + path . posix . relative ( publicDir , file )
141- builtUrl = await fileToUrl ( this , publicPath )
142- } else {
143- builtUrl = await fileToUrl ( this , file )
135+ // Get final asset URL. If the file does not exist,
136+ // we fall back to the initial URL and let it resolve in runtime
137+ let builtUrl : string | undefined
138+ if ( file ) {
139+ try {
140+ if ( publicDir && isParentDirectory ( publicDir , file ) ) {
141+ const publicPath = '/' + path . posix . relative ( publicDir , file )
142+ builtUrl = await fileToUrl ( this , publicPath )
143+ } else {
144+ builtUrl = await fileToUrl ( this , file )
145+ }
146+ } catch {
147+ // do nothing, we'll log a warning after this
144148 }
145- } catch {
146- // do nothing, we'll log a warning after this
147149 }
148- }
149- if ( ! builtUrl ) {
150- const rawExp = code . slice ( startIndex , endIndex )
151- config . logger . warnOnce (
152- `\n${ rawExp } doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
153- `If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.` ,
150+ if ( ! builtUrl ) {
151+ const rawExp = code . slice ( startIndex , endIndex )
152+ config . logger . warnOnce (
153+ `\n${ rawExp } doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
154+ `If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.` ,
155+ )
156+ builtUrl = url
157+ }
158+ s . update (
159+ startIndex ,
160+ endIndex ,
161+ `new URL(${ JSON . stringify ( builtUrl ) } , import.meta.url)` ,
154162 )
155- builtUrl = url
156163 }
157- s . update (
158- startIndex ,
159- endIndex ,
160- `new URL(${ JSON . stringify ( builtUrl ) } , import.meta.url)` ,
161- )
162- }
163- if ( s ) {
164- return transformStableResult ( s , id , config )
164+ if ( s ) {
165+ return transformStableResult ( s , id , config )
166+ }
165167 }
166- }
167- return null
168+ return null
169+ } ,
168170 } ,
169171 }
170172}
0 commit comments