Skip to content

Commit d5d9a31

Browse files
author
Jonas Kaltenbach
authored
fix(assetImportMetaUrl): allow ternary operator in template literal urls (#13121)
1 parent 0fd4616 commit d5d9a31

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

packages/vite/src/node/plugins/assetImportMetaUrl.ts

+22-5
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,14 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
6868

6969
// potential dynamic template string
7070
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
71-
let [pureUrl, queryString = ''] = rawUrl.split('?')
72-
if (queryString) {
73-
pureUrl += '`'
74-
queryString = '?' + queryString.slice(0, -1)
75-
}
71+
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
72+
const hasQueryDelimiter = queryDelimiterIndex !== -1
73+
const pureUrl = hasQueryDelimiter
74+
? rawUrl.slice(0, queryDelimiterIndex) + '`'
75+
: rawUrl
76+
const queryString = hasQueryDelimiter
77+
? rawUrl.slice(queryDelimiterIndex, -1)
78+
: ''
7679
const ast = this.parse(pureUrl)
7780
const templateLiteral = (ast as any).body[0].expression
7881
if (templateLiteral.expressions.length) {
@@ -180,3 +183,17 @@ function buildGlobPattern(ast: any) {
180183
}
181184
return pattern
182185
}
186+
187+
function getQueryDelimiterIndex(rawUrl: string): number {
188+
let bracketsStack = 0
189+
for (let i = 0; i < rawUrl.length; i++) {
190+
if (rawUrl[i] === '{') {
191+
bracketsStack++
192+
} else if (rawUrl[i] === '}') {
193+
bracketsStack--
194+
} else if (rawUrl[i] === '?' && bracketsStack === 0) {
195+
return i
196+
}
197+
}
198+
return -1
199+
}

playground/assets/__tests__/assets.spec.ts

+11
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,17 @@ test('new URL(`./${dynamic}?abc`, import.meta.url)', async () => {
344344
)
345345
})
346346

347+
test('new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)', async () => {
348+
expect(await page.textContent('.dynamic-import-meta-url-1-ternary')).toMatch(
349+
isBuild ? 'data:image/png;base64' : '/foo/nested/icon.png?abc',
350+
)
351+
expect(await page.textContent('.dynamic-import-meta-url-2-ternary')).toMatch(
352+
isBuild
353+
? /\/foo\/assets\/asset-\w{8}\.png\?abc/
354+
: '/foo/nested/asset.png?abc',
355+
)
356+
})
357+
347358
test('new URL(`non-existent`, import.meta.url)', async () => {
348359
expect(await page.textContent('.non-existent-import-meta-url')).toMatch(
349360
new URL('non-existent', page.url()).pathname,

playground/assets/index.html

+21
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ <h2>new URL(`./${dynamic}?abc`, import.meta.url)</h2>
239239
<code class="dynamic-import-meta-url-2-query"></code>
240240
</p>
241241

242+
<h2>new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)</h2>
243+
<p>
244+
<img class="dynamic-import-meta-url-img-1-ternary" />
245+
<code class="dynamic-import-meta-url-1-ternary"></code>
246+
</p>
247+
<p>
248+
<img class="dynamic-import-meta-url-img-2-ternary" />
249+
<code class="dynamic-import-meta-url-2-ternary"></code>
250+
</p>
251+
242252
<h2>new URL(`non-existent`, import.meta.url)</h2>
243253
<p>
244254
<code class="non-existent-import-meta-url"></code>
@@ -468,6 +478,17 @@ <h3>assets in noscript</h3>
468478
testDynamicImportMetaUrlWithQuery('icon', 1)
469479
testDynamicImportMetaUrlWithQuery('asset', 2)
470480

481+
function testDynamicImportMetaUrlWithTernaryOperator(name, i) {
482+
// prettier-ignore
483+
const metaUrl = new URL(`./nested/${1 === 0 ? 'failed' : name}.png?abc`, import.meta.url,)
484+
text(`.dynamic-import-meta-url-${i}-ternary`, metaUrl)
485+
document.querySelector(`.dynamic-import-meta-url-img-${i}-ternary`).src =
486+
metaUrl
487+
}
488+
489+
testDynamicImportMetaUrlWithTernaryOperator('icon', 1)
490+
testDynamicImportMetaUrlWithTernaryOperator('asset', 2)
491+
471492
{
472493
const name = 'test'
473494
const js = new URL(`./nested/${name}.js`, import.meta.url).href

0 commit comments

Comments
 (0)