From 534e1b1f663e6789277f899f55864379c62de334 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 13 Apr 2022 19:33:22 +0200 Subject: [PATCH 1/4] fix: handle url imports with semicolon (close #7717) --- packages/vite/src/node/__tests__/plugins/css.spec.ts | 6 ++++++ packages/vite/src/node/plugins/css.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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 '' }) From 72f03bcc4bdb0e5677de057ab5832bd6b3fa1813 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 13 Apr 2022 20:03:50 +0200 Subject: [PATCH 2/4] fix: handle data url --- packages/vite/src/node/__tests__/plugins/css.spec.ts | 8 ++++++++ packages/vite/src/node/plugins/css.ts | 11 +++++++---- 2 files changed, 15 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 0f5aed60a00a5e..078cec2e0f3d77 100644 --- a/packages/vite/src/node/__tests__/plugins/css.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/css.spec.ts @@ -128,6 +128,14 @@ describe('hoist @ rules', () => { 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 e786dcdf56ae5b..b9d66b3d5d7c2b 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*(?:url\()?(?:"[^"]*"|'[^']*'|[^;]*).*?;/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 From 4fd28101351f87398c584c09146a5f41b5bebed5 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 13 Apr 2022 20:17:14 +0200 Subject: [PATCH 3/4] fix: update hoist regexp --- packages/vite/src/node/plugins/css.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index b9d66b3d5d7c2b..af6a2b0362ba51 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1113,7 +1113,7 @@ export async function hoistAtRules(css: string) { // to top when multiple files are concatenated. // match until semicolon that's not in quotes s.replace( - /@import\s*(?:url)?(?:"[^"]*"|'[^']*'|\([^)]*\)|[^;]*).*?;/gm, + /@import\s*(?:url\()?(?:[^)]*\)|"[^"]*"|'[^']*'|[^;]*).*?;/gm, (match) => { s.appendLeft(0, match) return '' From 784bcc30d3f6985a11c2dab400b4b52deecab2ec Mon Sep 17 00:00:00 2001 From: patak-dev Date: Wed, 13 Apr 2022 21:23:50 +0200 Subject: [PATCH 4/4] chore: simplify regex --- packages/vite/src/node/plugins/css.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index af6a2b0362ba51..0a14e091c53637 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1113,7 +1113,7 @@ export async function hoistAtRules(css: string) { // to top when multiple files are concatenated. // match until semicolon that's not in quotes s.replace( - /@import\s*(?:url\()?(?:[^)]*\)|"[^"]*"|'[^']*'|[^;]*).*?;/gm, + /@import\s*(?:url\([^\)]*\)|"[^"]*"|'[^']*'|[^;]*).*?;/gm, (match) => { s.appendLeft(0, match) return ''