Skip to content

Commit fa2e47f

Browse files
sapphi-redfrank
and
frank
authored
fix(css): url() with variable in sass/less (fixes #3644, #7651) (#10741)
Co-authored-by: frank <frank@hebingjundeMacBook-Pro.local>
1 parent 1358a3c commit fa2e47f

13 files changed

+49
-18
lines changed

packages/vite/src/node/plugins/css.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -1495,7 +1495,7 @@ const scss: SassStylePreprocessor = async (
14951495
const internalImporter: Sass.Importer = (url, importer, done) => {
14961496
resolvers.sass(url, importer).then((resolved) => {
14971497
if (resolved) {
1498-
rebaseUrls(resolved, options.filename, options.alias)
1498+
rebaseUrls(resolved, options.filename, options.alias, '$')
14991499
.then((data) => done?.(data))
15001500
.catch((data) => done?.(data))
15011501
} else {
@@ -1579,7 +1579,8 @@ const sass: SassStylePreprocessor = (source, root, options, aliasResolver) =>
15791579
async function rebaseUrls(
15801580
file: string,
15811581
rootFile: string,
1582-
alias: Alias[]
1582+
alias: Alias[],
1583+
variablePrefix: string
15831584
): Promise<Sass.ImporterReturnType> {
15841585
file = path.resolve(file) // ensure os-specific flashes
15851586
// in the same dir, no need to rebase
@@ -1604,6 +1605,8 @@ async function rebaseUrls(
16041605
let rebased
16051606
const rebaseFn = (url: string) => {
16061607
if (url.startsWith('/')) return url
1608+
// ignore url's starting with variable
1609+
if (url.startsWith(variablePrefix)) return url
16071610
// match alias, no need to rewrite
16081611
for (const { find } of alias) {
16091612
const matches =
@@ -1736,7 +1739,12 @@ function createViteLessPlugin(
17361739
path.join(dir, '*')
17371740
)
17381741
if (resolved) {
1739-
const result = await rebaseUrls(resolved, this.rootFile, this.alias)
1742+
const result = await rebaseUrls(
1743+
resolved,
1744+
this.rootFile,
1745+
this.alias,
1746+
'@'
1747+
)
17401748
let contents: string
17411749
if (result && 'contents' in result) {
17421750
contents = result.contents

playground/css/__tests__/css.spec.ts

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
removeFile,
1111
serverLogs,
1212
untilUpdated,
13+
viteTestUrl,
1314
withRetry
1415
} from '~utils'
1516

@@ -78,6 +79,7 @@ test('sass', async () => {
7879
const imported = await page.$('.sass')
7980
const atImport = await page.$('.sass-at-import')
8081
const atImportAlias = await page.$('.sass-at-import-alias')
82+
const urlStartsWithVariable = await page.$('.sass-url-starts-with-variable')
8183
const partialImport = await page.$('.sass-partial')
8284

8385
expect(await getColor(imported)).toBe('orange')
@@ -87,6 +89,9 @@ test('sass', async () => {
8789
expect(await getBg(atImportAlias)).toMatch(
8890
isBuild ? /base64/ : '/nested/icon.png'
8991
)
92+
expect(await getBg(urlStartsWithVariable)).toMatch(
93+
isBuild ? /ok\.\w+\.png/ : `${viteTestUrl}/ok.png`
94+
)
9095
expect(await getColor(partialImport)).toBe('orchid')
9196

9297
editFile('sass.scss', (code) =>
@@ -109,6 +114,7 @@ test('less', async () => {
109114
const imported = await page.$('.less')
110115
const atImport = await page.$('.less-at-import')
111116
const atImportAlias = await page.$('.less-at-import-alias')
117+
const urlStartsWithVariable = await page.$('.less-url-starts-with-variable')
112118

113119
expect(await getColor(imported)).toBe('blue')
114120
expect(await getColor(atImport)).toBe('darkslateblue')
@@ -117,6 +123,9 @@ test('less', async () => {
117123
expect(await getBg(atImportAlias)).toMatch(
118124
isBuild ? /base64/ : '/nested/icon.png'
119125
)
126+
expect(await getBg(urlStartsWithVariable)).toMatch(
127+
isBuild ? /ok\.\w+\.png/ : `${viteTestUrl}/ok.png`
128+
)
120129

121130
editFile('less.less', (code) => code.replace('@color: blue', '@color: red'))
122131
await untilUpdated(() => getColor(imported), 'red')
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
.path-resolving-css {
2-
composes: apply-color from '@/composed.module.css';
2+
composes: apply-color from '=/composed.module.css';
33
}
44

55
.path-resolving-sass {
6-
composes: apply-color from '@/composed.module.scss';
6+
composes: apply-color from '=/composed.module.scss';
77
}
88

99
.path-resolving-less {
10-
composes: apply-color from '@/composed.module.less';
10+
composes: apply-color from '=/composed.module.less';
1111
}

playground/css/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ <h1>CSS</h1>
3232
contains alias
3333
</p>
3434
<p class="sass-partial">@import from SASS _partial: This should be orchid</p>
35+
<p class="sass-url-starts-with-variable">url starts with variable</p>
3536
<p>Imported SASS string:</p>
3637
<pre class="imported-sass"></pre>
3738
<p class="sass-dep">
@@ -46,6 +47,7 @@ <h1>CSS</h1>
4647
@import from Less: This should be darkslateblue and have bg image which url
4748
contains alias
4849
</p>
50+
<p class="less-url-starts-with-variable">url starts with variable</p>
4951
<p>Imported Less string:</p>
5052
<pre class="imported-less"></pre>
5153

playground/css/less.less

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '@/nested/nested';
1+
@import '=/nested/nested';
22
@import './nested/css-in-less.less';
33

44
// Test data-uri calls with relative images.

playground/css/linked.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '@/linked-at-import.css';
1+
@import '=/linked-at-import.css';
22

33
/* test postcss nesting */
44
.wrapper {

playground/css/nested/_index.scss

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,11 @@
77

88
.sass-at-import-alias {
99
color: olive;
10-
background: url(@/nested/icon.png) 10px no-repeat;
10+
background: url(=/nested/icon.png) 10px no-repeat;
11+
}
12+
13+
$var: '/ok.png';
14+
.sass-url-starts-with-variable {
15+
background: url($var);
16+
background-position: center;
1117
}

playground/css/nested/nested.less

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,11 @@
55

66
.less-at-import-alias {
77
color: darkslateblue;
8-
background: url(@/nested/icon.png) 10px no-repeat;
8+
background: url(=/nested/icon.png) 10px no-repeat;
9+
}
10+
11+
@var: '/ok.png';
12+
.less-url-starts-with-variable {
13+
background: url('@{var}');
14+
background-position: center;
915
}

playground/css/nested/nested.sss

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55

66
.sugarss-at-import-alias
77
color: darkslateblue
8-
background: url(@/nested/icon.png) 10px no-repeat
8+
background: url(=/nested/icon.png) 10px no-repeat

playground/css/nested/nested.styl

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
.stylus-import-alias
55
color darkslateblue
6-
background url('@/nested/icon.png') 10px no-repeat
6+
background url('=/nested/icon.png') 10px no-repeat

playground/css/sass.scss

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
@import '@/nested'; // alias + custom index resolving -> /nested/_index.scss
2-
@import '@/nested/partial'; // sass convention: omitting leading _ for partials
1+
@import '=/nested'; // alias + custom index resolving -> /nested/_index.scss
2+
@import '=/nested/partial'; // sass convention: omitting leading _ for partials
33
@import 'css-dep'; // package w/ sass entry points
44
@import 'virtual-dep'; // virtual file added through importer
5-
@import '@/pkg-dep'; // package w/out sass field
6-
@import '@/weapp.wxss'; // wxss file
5+
@import '=/pkg-dep'; // package w/out sass field
6+
@import '=/weapp.wxss'; // wxss file
77

88
.sass {
99
/* injected via vite.config.js */

playground/css/sugarss.sss

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '@/nested/nested.sss'
1+
@import '=/nested/nested.sss'
22
33
.sugarss
44
color: blue

playground/css/vite.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = {
1414
},
1515
resolve: {
1616
alias: {
17-
'@': __dirname,
17+
'=': __dirname,
1818
spacefolder: __dirname + '/folder with space',
1919
'#alias': __dirname + '/aliased/foo.css',
2020
'#alias-module': __dirname + '/aliased/bar.module.css'

0 commit comments

Comments
 (0)