Skip to content

Commit f8ebd54

Browse files
Enable URL rewriting for PostCSS
1 parent b676da8 commit f8ebd54

File tree

5 files changed

+120
-8
lines changed

5 files changed

+120
-8
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- _Experimental_: Add `user-valid` and `user-invalid` variants ([#12370](https://github.com/tailwindlabs/tailwindcss/pull/12370))
1818
- _Experimental_: Add `wrap-anywhere`, `wrap-break-word`, and `wrap-normal` utilities ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128))
1919

20+
### Fixed
21+
22+
- Vite: Fix an issue where `url(…)` rebasing in transitively imported CSS files is not resolved correctly
23+
- PostCSS: Rebase `url(…)` in CSS imported CSS files
24+
2025
## [4.0.11] - 2025-03-06
2126

2227
### Fixed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { binary, css, js, json, svg, test } from '../utils'
2+
3+
const SIMPLE_IMAGE = `iVBORw0KGgoAAAANSUhEUgAAADAAAAAlAQAAAAAsYlcCAAAACklEQVR4AWMYBQABAwABRUEDtQAAAABJRU5ErkJggg==`
4+
5+
test.debug(
6+
'can rewrite urls in production builds',
7+
{
8+
fs: {
9+
'package.json': json`
10+
{
11+
"dependencies": {
12+
"postcss": "^8",
13+
"postcss-cli": "^10",
14+
"tailwindcss": "workspace:^",
15+
"@tailwindcss/postcss": "workspace:^"
16+
}
17+
}
18+
`,
19+
'postcss.config.js': js`
20+
module.exports = {
21+
plugins: {
22+
'@tailwindcss/postcss': {},
23+
},
24+
}
25+
`,
26+
'src/index.css': css`
27+
@reference 'tailwindcss';
28+
@import './dir-1/bar.css';
29+
@import './dir-1/dir-2/baz.css';
30+
@import './dir-1/dir-2/vector.css';
31+
`,
32+
'src/dir-1/bar.css': css`
33+
.test1 {
34+
background-image: url('../../resources/image.png');
35+
}
36+
`,
37+
'src/dir-1/dir-2/baz.css': css`
38+
.test2 {
39+
background-image: url('../../../resources/image.png');
40+
}
41+
`,
42+
'src/dir-1/dir-2/vector.css': css`
43+
@import './dir-3/vector.css';
44+
.test3 {
45+
background-image: url('../../../resources/vector.svg');
46+
}
47+
`,
48+
'src/dir-1/dir-2/dir-3/vector.css': css`
49+
.test4 {
50+
background-image: url('./vector-2.svg');
51+
}
52+
`,
53+
'resources/image.png': binary(SIMPLE_IMAGE),
54+
'resources/vector.svg': svg`
55+
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
56+
<rect width="100%" height="100%" fill="red" />
57+
<circle cx="200" cy="100" r="80" fill="green" />
58+
<rect width="100%" height="100%" fill="red" />
59+
<circle cx="200" cy="100" r="80" fill="green" />
60+
</svg>
61+
`,
62+
'src/dir-1/dir-2/dir-3/vector-2.svg': svg`
63+
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
64+
<rect width="100%" height="100%" fill="blue" />
65+
<circle cx="200" cy="100" r="80" fill="green" />
66+
<rect width="100%" height="100%" fill="red" />
67+
<circle cx="200" cy="100" r="80" fill="pink" />
68+
</svg>
69+
`,
70+
},
71+
},
72+
async ({ fs, exec, expect }) => {
73+
await exec('pnpm postcss src/index.css --output dist/out.css')
74+
75+
expect(await fs.dumpFiles('dist/out.css')).toMatchInlineSnapshot(`
76+
"
77+
--- dist/out.css ---
78+
.test1 {
79+
background-image: url('../resources/image.png');
80+
}
81+
.test2 {
82+
background-image: url('../resources/image.png');
83+
}
84+
.test4 {
85+
background-image: url('./dir-1/dir-2/dir-3/vector-2.svg');
86+
}
87+
.test3 {
88+
background-image: url('../resources/vector.svg');
89+
}
90+
"
91+
`)
92+
},
93+
)

integrations/vite/url-rewriting.test.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,36 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
4242
</head>
4343
<body>
4444
<div id="app"></div>
45-
<script type="module" src="./src/main.ts"></script>
4645
</body>
4746
</html>
4847
`,
49-
'src/main.ts': ts``,
5048
'src/app.css': css`
49+
@reference 'tailwindcss';
5150
@import './dir-1/bar.css';
5251
@import './dir-1/dir-2/baz.css';
5352
@import './dir-1/dir-2/vector.css';
5453
`,
5554
'src/dir-1/bar.css': css`
56-
.bar {
55+
.test1 {
5756
background-image: url('../../resources/image.png');
5857
}
5958
`,
6059
'src/dir-1/dir-2/baz.css': css`
61-
.baz {
60+
.test2 {
6261
background-image: url('../../../resources/image.png');
6362
}
6463
`,
6564
'src/dir-1/dir-2/vector.css': css`
66-
.baz {
65+
@import './dir-3/vector.css';
66+
.test3 {
6767
background-image: url('../../../resources/vector.svg');
6868
}
6969
`,
70+
'src/dir-1/dir-2/dir-3/vector.css': css`
71+
.test4 {
72+
background-image: url('./vector-2.svg');
73+
}
74+
`,
7075
'resources/image.png': binary(SIMPLE_IMAGE),
7176
'resources/vector.svg': svg`
7277
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
@@ -76,6 +81,14 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
7681
<circle cx="200" cy="100" r="80" fill="green" />
7782
</svg>
7883
`,
84+
'src/dir-1/dir-2/dir-3/vector-2.svg': svg`
85+
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
86+
<rect width="100%" height="100%" fill="blue" />
87+
<circle cx="200" cy="100" r="80" fill="green" />
88+
<rect width="100%" height="100%" fill="red" />
89+
<circle cx="200" cy="100" r="80" fill="pink" />
90+
</svg>
91+
`,
7992
},
8093
},
8194
async ({ fs, exec, expect }) => {
@@ -87,7 +100,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
87100
await fs.expectFileToContain(files[0][0], [SIMPLE_IMAGE])
88101

89102
let images = await fs.glob('dist/**/*.svg')
90-
expect(images).toHaveLength(1)
103+
expect(images).toHaveLength(2)
91104

92105
await fs.expectFileToContain(files[0][0], [/\/assets\/vector-.*?\.svg/])
93106
},

packages/@tailwindcss-node/src/compile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ function createCompileOptions({
4040
async loadModule(id: string, base: string) {
4141
return loadModule(id, base, onDependency, customJsResolver)
4242
},
43-
async loadStylesheet(id: string, base: string) {
44-
let sheet = await loadStylesheet(id, base, onDependency, customCssResolver)
43+
async loadStylesheet(id: string, sheetBase: string) {
44+
let sheet = await loadStylesheet(id, sheetBase, onDependency, customCssResolver)
4545

4646
if (shouldRewriteUrls) {
4747
sheet.content = await rewriteUrls({

packages/@tailwindcss-postcss/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
110110
DEBUG && I.start('Create compiler')
111111
let compiler = await compileAst(ast, {
112112
base: inputBasePath,
113+
shouldRewriteUrls: true,
113114
onDependency: (path) => {
114115
context.fullRebuildPaths.push(path)
115116
},

0 commit comments

Comments
 (0)