From a5c2a7803eeed55e023bec464f6b193ed5ddac79 Mon Sep 17 00:00:00 2001 From: Hugo ATTAL Date: Wed, 13 Apr 2022 21:39:46 +0200 Subject: [PATCH] fix: handle url imports with semicolon (fix #7717) (#7718) --- .../vite/src/node/__tests__/plugins/css.spec.ts | 14 ++++++++++++++ packages/vite/src/node/plugins/css.ts | 11 +++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/node/__tests__/plugins/css.spec.ts b/packages/vite/src/node/__tests__/plugins/css.spec.ts index 9b652a563ccb0a..078cec2e0f3d77 100644 --- a/packages/vite/src/node/__tests__/plugins/css.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/css.spec.ts @@ -122,6 +122,20 @@ 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 url data with semicolon', async () => { + const css = `.foo{color:red;}@import url(data:image/png;base64,iRxVB0);` + const result = await hoistAtRules(css) + expect(result).toBe( + `@import url(data:image/png;base64,iRxVB0);.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..0a14e091c53637 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1112,10 +1112,13 @@ 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.appendLeft(0, match) - return '' - }) + s.replace( + /@import\s*(?:url\([^\)]*\)|"[^"]*"|'[^']*'|[^;]*).*?;/gm, + (match) => { + s.appendLeft(0, match) + return '' + } + ) // #6333 // CSS @charset must be the top-first in the file, hoist the first to top let foundCharset = false