diff --git a/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts b/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts new file mode 100644 index 00000000000000..37dc870372da0f --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts @@ -0,0 +1,65 @@ +import { describe, expect, test } from 'vitest' +import { parseAst } from 'rollup/parseAst' +import { assetImportMetaUrlPlugin } from '../../plugins/assetImportMetaUrl' +import { resolveConfig } from '../../config' +import { PartialEnvironment } from '../../baseEnvironment' + +async function createAssetImportMetaurlPluginTransform() { + const config = await resolveConfig({ configFile: false }, 'serve') + const instance = assetImportMetaUrlPlugin(config) + const environment = new PartialEnvironment('client', config) + + return async (code: string) => { + // @ts-expect-error transform should exist + const result = await instance.transform.call( + { environment, parse: parseAst }, + code, + 'foo.ts', + ) + return result?.code || result + } +} + +describe('assetImportMetaUrlPlugin', async () => { + const transform = await createAssetImportMetaurlPluginTransform() + + test('variable between /', async () => { + expect( + await transform('new URL(`./foo/${dir}/index.js`, import.meta.url)'), + ).toMatchInlineSnapshot( + `"new URL((import.meta.glob("./foo/*/index.js", {"eager":true,"import":"default","query":"?url"}))[\`./foo/\${dir}/index.js\`], import.meta.url)"`, + ) + }) + + test('variable before non-/', async () => { + expect( + await transform('new URL(`./foo/${dir}.js`, import.meta.url)'), + ).toMatchInlineSnapshot( + `"new URL((import.meta.glob("./foo/*.js", {"eager":true,"import":"default","query":"?url"}))[\`./foo/\${dir}.js\`], import.meta.url)"`, + ) + }) + + test('two variables', async () => { + expect( + await transform('new URL(`./foo/${dir}${file}.js`, import.meta.url)'), + ).toMatchInlineSnapshot( + `"new URL((import.meta.glob("./foo/*.js", {"eager":true,"import":"default","query":"?url"}))[\`./foo/\${dir}\${file}.js\`], import.meta.url)"`, + ) + }) + + test('two variables between /', async () => { + expect( + await transform( + 'new URL(`./foo/${dir}${dir2}/index.js`, import.meta.url)', + ), + ).toMatchInlineSnapshot( + `"new URL((import.meta.glob("./foo/*/index.js", {"eager":true,"import":"default","query":"?url"}))[\`./foo/\${dir}\${dir2}/index.js\`], import.meta.url)"`, + ) + }) + + test('ignore starting with a variable', async () => { + expect( + await transform('new URL(`${file}.js`, import.meta.url)'), + ).toMatchInlineSnapshot(`"new URL(\`\${file}.js\`, import.meta.url)"`) + }) +}) diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index 03686fc638cb9a..ba3e434d44d2a0 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -81,7 +81,7 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { const templateLiteral = (ast as any).body[0].expression if (templateLiteral.expressions.length) { const pattern = buildGlobPattern(templateLiteral) - if (pattern.startsWith('**')) { + if (pattern.startsWith('*')) { // don't transform for patterns like this // because users won't intend to do that in most cases continue @@ -168,19 +168,18 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { function buildGlobPattern(ast: any) { let pattern = '' - let lastElementIndex = -1 - for (const exp of ast.expressions) { - for (let i = lastElementIndex + 1; i < ast.quasis.length; i++) { - const el = ast.quasis[i] - if (el.end < exp.start) { - pattern += el.value.raw - lastElementIndex = i - } + let lastIsGlob = false + for (let i = 0; i < ast.quasis.length; i++) { + const str = ast.quasis[i].value.raw + if (str) { + pattern += str + lastIsGlob = false + } + + if (ast.expressions[i] && !lastIsGlob) { + pattern += '*' + lastIsGlob = true } - pattern += '**' - } - for (let i = lastElementIndex + 1; i < ast.quasis.length; i++) { - pattern += ast.quasis[i].value.raw } return pattern }