diff --git a/packages/vite/src/node/__tests__/plugins/css.spec.ts b/packages/vite/src/node/__tests__/plugins/css.spec.ts index 9b652a563ccb0a..0f5aed60a00a5e 100644 --- a/packages/vite/src/node/__tests__/plugins/css.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/css.spec.ts @@ -122,6 +122,12 @@ describe('hoist @ rules', () => { expect(result).toBe(`@import "bla";.foo{color:red;}`) }) + test('hoist @import url with semicolon', async () => { + const css = `.foo{color:red;}@import url("bla;bla");` + const result = await hoistAtRules(css) + expect(result).toBe(`@import url("bla;bla");.foo{color:red;}`) + }) + test('hoist @import with semicolon in quotes', async () => { const css = `.foo{color:red;}@import "bla;bar";` const result = await hoistAtRules(css) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 08bdfbeed4e616..e786dcdf56ae5b 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1112,7 +1112,7 @@ export async function hoistAtRules(css: string) { // CSS @import can only appear at top of the file. We need to hoist all @import // to top when multiple files are concatenated. // match until semicolon that's not in quotes - s.replace(/@import\s*(?:"[^"]*"|'[^']*'|[^;]*).*?;/gm, (match) => { + s.replace(/@import\s*(?:url\()?(?:"[^"]*"|'[^']*'|[^;]*).*?;/gm, (match) => { s.appendLeft(0, match) return '' })