Skip to content

Commit

Permalink
fix(assetImportMetaUrl): allow ternary operator in template literal u…
Browse files Browse the repository at this point in the history
…rls (#13121)
  • Loading branch information
Jonas Kaltenbach committed May 16, 2023
1 parent 0fd4616 commit d5d9a31
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
27 changes: 22 additions & 5 deletions packages/vite/src/node/plugins/assetImportMetaUrl.ts
Expand Up @@ -68,11 +68,14 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {

// potential dynamic template string
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
let [pureUrl, queryString = ''] = rawUrl.split('?')
if (queryString) {
pureUrl += '`'
queryString = '?' + queryString.slice(0, -1)
}
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
const hasQueryDelimiter = queryDelimiterIndex !== -1
const pureUrl = hasQueryDelimiter
? rawUrl.slice(0, queryDelimiterIndex) + '`'
: rawUrl
const queryString = hasQueryDelimiter
? rawUrl.slice(queryDelimiterIndex, -1)
: ''
const ast = this.parse(pureUrl)
const templateLiteral = (ast as any).body[0].expression
if (templateLiteral.expressions.length) {
Expand Down Expand Up @@ -180,3 +183,17 @@ function buildGlobPattern(ast: any) {
}
return pattern
}

function getQueryDelimiterIndex(rawUrl: string): number {
let bracketsStack = 0
for (let i = 0; i < rawUrl.length; i++) {
if (rawUrl[i] === '{') {
bracketsStack++
} else if (rawUrl[i] === '}') {
bracketsStack--
} else if (rawUrl[i] === '?' && bracketsStack === 0) {
return i
}
}
return -1
}
11 changes: 11 additions & 0 deletions playground/assets/__tests__/assets.spec.ts
Expand Up @@ -344,6 +344,17 @@ test('new URL(`./${dynamic}?abc`, import.meta.url)', async () => {
)
})

test('new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)', async () => {
expect(await page.textContent('.dynamic-import-meta-url-1-ternary')).toMatch(
isBuild ? 'data:image/png;base64' : '/foo/nested/icon.png?abc',
)
expect(await page.textContent('.dynamic-import-meta-url-2-ternary')).toMatch(
isBuild
? /\/foo\/assets\/asset-\w{8}\.png\?abc/
: '/foo/nested/asset.png?abc',
)
})

test('new URL(`non-existent`, import.meta.url)', async () => {
expect(await page.textContent('.non-existent-import-meta-url')).toMatch(
new URL('non-existent', page.url()).pathname,
Expand Down
21 changes: 21 additions & 0 deletions playground/assets/index.html
Expand Up @@ -239,6 +239,16 @@ <h2>new URL(`./${dynamic}?abc`, import.meta.url)</h2>
<code class="dynamic-import-meta-url-2-query"></code>
</p>

<h2>new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)</h2>
<p>
<img class="dynamic-import-meta-url-img-1-ternary" />
<code class="dynamic-import-meta-url-1-ternary"></code>
</p>
<p>
<img class="dynamic-import-meta-url-img-2-ternary" />
<code class="dynamic-import-meta-url-2-ternary"></code>
</p>

<h2>new URL(`non-existent`, import.meta.url)</h2>
<p>
<code class="non-existent-import-meta-url"></code>
Expand Down Expand Up @@ -468,6 +478,17 @@ <h3>assets in noscript</h3>
testDynamicImportMetaUrlWithQuery('icon', 1)
testDynamicImportMetaUrlWithQuery('asset', 2)

function testDynamicImportMetaUrlWithTernaryOperator(name, i) {
// prettier-ignore
const metaUrl = new URL(`./nested/${1 === 0 ? 'failed' : name}.png?abc`, import.meta.url,)
text(`.dynamic-import-meta-url-${i}-ternary`, metaUrl)
document.querySelector(`.dynamic-import-meta-url-img-${i}-ternary`).src =
metaUrl
}

testDynamicImportMetaUrlWithTernaryOperator('icon', 1)
testDynamicImportMetaUrlWithTernaryOperator('asset', 2)

{
const name = 'test'
const js = new URL(`./nested/${name}.js`, import.meta.url).href
Expand Down

0 comments on commit d5d9a31

Please sign in to comment.