From c4b532cc900bf988073583511f57bd581755d5e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BF=A0=20/=20green?=
Date: Mon, 16 Dec 2024 20:43:52 +0900
Subject: [PATCH] fix(css): root relative import in sass modern API on Windows
(#18945)
---
packages/vite/src/node/plugins/css.ts | 10 ++++++++--
playground/css/__tests__/css.spec.ts | 1 +
playground/css/index.html | 3 +++
playground/css/nested/_index.scss | 1 +
playground/css/nested/root-relative.scss | 3 +++
5 files changed, 16 insertions(+), 2 deletions(-)
create mode 100644 playground/css/nested/root-relative.scss
diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts
index 04c0f87982fa2e..3453cadf1d2332 100644
--- a/packages/vite/src/node/plugins/css.ts
+++ b/packages/vite/src/node/plugins/css.ts
@@ -82,7 +82,7 @@ import {
urlRE,
} from '../utils'
import type { Logger } from '../logger'
-import { cleanUrl, slash } from '../../shared/utils'
+import { cleanUrl, isWindows, slash } from '../../shared/utils'
import { createBackCompatIdResolver } from '../idResolver'
import type { ResolveIdFn } from '../idResolver'
import { PartialEnvironment } from '../baseEnvironment'
@@ -1162,8 +1162,14 @@ function createCSSResolvers(config: ResolvedConfig): CSSAtImportResolvers {
preferRelative: true,
})
sassResolve = async (...args) => {
+ // the modern API calls `canonicalize` with resolved file URLs
+ // for relative URLs before raw specifiers
if (args[1].startsWith('file://')) {
- args[1] = fileURLToPath(args[1])
+ args[1] = fileURLToPath(args[1], {
+ windows:
+ // file:///foo cannot be converted to path with windows mode
+ isWindows && args[1].startsWith('file:///') ? false : undefined,
+ })
}
return resolver(...args)
}
diff --git a/playground/css/__tests__/css.spec.ts b/playground/css/__tests__/css.spec.ts
index 553a1c70331793..f0ff63c6b5dbb5 100644
--- a/playground/css/__tests__/css.spec.ts
+++ b/playground/css/__tests__/css.spec.ts
@@ -101,6 +101,7 @@ test('sass', async () => {
expect(await getColor(partialImport)).toBe('orchid')
expect(await getColor(await page.$('.sass-file-absolute'))).toBe('orange')
expect(await getColor(await page.$('.sass-dir-index'))).toBe('orange')
+ expect(await getColor(await page.$('.sass-root-relative'))).toBe('orange')
if (isBuild) return
diff --git a/playground/css/index.html b/playground/css/index.html
index 45525412570992..9918757eb1bee6 100644
--- a/playground/css/index.html
+++ b/playground/css/index.html
@@ -43,6 +43,9 @@ CSS
@import "file:///xxx/absolute-path.scss" should be orange
@import "./dir" should be orange
+
+ @import "/nested/root-relative.scss" should be orange
+
Less: This should be blue
diff --git a/playground/css/nested/_index.scss b/playground/css/nested/_index.scss
index 72e6b14268334e..ff81e7d82351b9 100644
--- a/playground/css/nested/_index.scss
+++ b/playground/css/nested/_index.scss
@@ -1,4 +1,5 @@
@use 'sass:string';
+@use '/nested/root-relative'; // root relative path
@import './css-in-scss.css';
diff --git a/playground/css/nested/root-relative.scss b/playground/css/nested/root-relative.scss
new file mode 100644
index 00000000000000..775dca855743b3
--- /dev/null
+++ b/playground/css/nested/root-relative.scss
@@ -0,0 +1,3 @@
+.sass-root-relative {
+ color: orange;
+}