Skip to content

Commit 2294a33

Browse files
committed
Tailwind v4 with patch
1 parent b642b72 commit 2294a33

File tree

8 files changed

+659
-377
lines changed

8 files changed

+659
-377
lines changed

package-lock.json

Lines changed: 432 additions & 308 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"format": "prettier --write .",
1515
"format:check": "prettier --check .",
1616
"lint": "next lint --fix",
17-
"lint:check": "next lint"
17+
"lint:check": "next lint",
18+
"postinstall": "node scripts/patch-plasmo-with-tailwind-4.js"
1819
},
1920
"dependencies": {
2021
"@emotion/react": "^11.14.0",
@@ -33,12 +34,12 @@
3334
"react-dom": "^19.1.0"
3435
},
3536
"devDependencies": {
37+
"@tailwindcss/postcss": "^4.1.14",
3638
"@types/chrome": "^0.0.318",
3739
"@types/node": "^22.15.3",
3840
"@types/react": "^19.1.2",
3941
"@types/react-dom": "^19.1.3",
4042
"@typescript-eslint/eslint-plugin": "^8.31.1",
41-
"autoprefixer": "^10.4.21",
4243
"cross-env": "^7.0.3",
4344
"eslint": "^9.26.0",
4445
"eslint-config-next": "^15.3.1",
@@ -49,7 +50,7 @@
4950
"eslint-plugin-simple-import-sort": "^12.1.1",
5051
"postcss": "^8.5.3",
5152
"prettier": "^3.5.3",
52-
"tailwindcss": "^3.4.17",
53+
"tailwindcss": "^4.1.14",
5354
"typescript": "^5.8.3"
5455
},
5556
"eslintConfig": {

postcss.config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*/
44
module.exports = {
55
plugins: {
6-
tailwindcss: {},
7-
autoprefixer: {},
6+
'@tailwindcss/postcss': {},
87
},
98
};
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Plasmo + Tailwind v4 Compatibility Patch
5+
*
6+
* Automatically fixes "node:" import issues in jiti and @tailwindcss/oxide
7+
* that cause Plasmo builds to fail when using Tailwind CSS v4.
8+
*
9+
* @see https://github.com/PlasmoHQ/plasmo/issues/1188
10+
*/
11+
12+
const fs = require('fs');
13+
const path = require('path');
14+
15+
// Console colors
16+
const c = {
17+
reset: '\x1b[0m',
18+
red: '\x1b[31m',
19+
green: '\x1b[32m',
20+
yellow: '\x1b[33m',
21+
blue: '\x1b[34m',
22+
cyan: '\x1b[36m',
23+
};
24+
25+
const log = (msg, color = 'reset') =>
26+
console.log(`${c[color]}${msg}${c.reset}`);
27+
28+
/**
29+
* Find package files that need patching
30+
*/
31+
const findPackageFiles = () => {
32+
const nodeModules = path.resolve('node_modules');
33+
if (!fs.existsSync(nodeModules)) return [];
34+
35+
const files = [];
36+
const pnpmPath = path.join(nodeModules, '.pnpm');
37+
38+
// Helper to safely read directory
39+
const readDir = (dir) => {
40+
try {
41+
return fs.existsSync(dir) ? fs.readdirSync(dir) : [];
42+
} catch {
43+
return [];
44+
}
45+
};
46+
47+
// Helper to check file exists
48+
const fileExists = (filePath) => {
49+
try {
50+
return fs.existsSync(filePath);
51+
} catch {
52+
return false;
53+
}
54+
};
55+
56+
// Find jiti files
57+
const findJitiFiles = (basePath) => {
58+
const jitiPath = path.join(basePath, 'jiti');
59+
if (!fileExists(jitiPath)) return [];
60+
61+
const targets = ['dist/jiti.cjs', 'dist/babel.cjs', 'lib/jiti.cjs'];
62+
63+
return targets
64+
.map((target) => path.join(jitiPath, target))
65+
.filter(fileExists);
66+
};
67+
68+
// Find oxide files
69+
const findOxideFiles = (basePath) => {
70+
const oxidePath = path.join(basePath, '@tailwindcss', 'oxide', 'index.js');
71+
return fileExists(oxidePath) ? [oxidePath] : [];
72+
};
73+
74+
// Search pnpm structure
75+
if (fileExists(pnpmPath)) {
76+
readDir(pnpmPath).forEach((entry) => {
77+
if (entry.startsWith('jiti@')) {
78+
const packagePath = path.join(pnpmPath, entry, 'node_modules');
79+
files.push(...findJitiFiles(packagePath));
80+
}
81+
82+
if (
83+
entry.startsWith('@tailwindcss+oxide@') ||
84+
entry.startsWith('%40tailwindcss+oxide@')
85+
) {
86+
const packagePath = path.join(pnpmPath, entry, 'node_modules');
87+
files.push(...findOxideFiles(packagePath));
88+
}
89+
});
90+
}
91+
92+
// Search regular node_modules
93+
files.push(...findJitiFiles(nodeModules));
94+
files.push(...findOxideFiles(nodeModules));
95+
96+
return [...new Set(files)]; // Remove duplicates
97+
};
98+
99+
/**
100+
* Patch a single file
101+
*/
102+
const patchFile = (filePath) => {
103+
try {
104+
if (!fs.existsSync(filePath)) {
105+
log(`⚠️ File not found: ${path.basename(filePath)}`, 'yellow');
106+
return false;
107+
}
108+
109+
const content = fs.readFileSync(filePath, 'utf8');
110+
const hasNodeImports =
111+
content.includes('require("node:') || content.includes("require('node:");
112+
113+
if (!hasNodeImports) {
114+
log(`✅ ${path.basename(filePath)} - already patched`, 'green');
115+
return true;
116+
}
117+
118+
// Apply patches for both quote styles
119+
const patched = content
120+
.replace(/require\("node:([^"]+)"\)/g, 'require("$1")')
121+
.replace(/require\('node:([^']+)'\)/g, "require('$1')");
122+
123+
fs.writeFileSync(filePath, patched, 'utf8');
124+
log(`✅ ${path.basename(filePath)} - patched successfully`, 'green');
125+
return true;
126+
} catch (error) {
127+
log(`❌ ${path.basename(filePath)} - error: ${error.message}`, 'red');
128+
return false;
129+
}
130+
};
131+
132+
/**
133+
* Main execution
134+
*/
135+
const main = () => {
136+
log('🔧 Plasmo + Tailwind v4 compatibility patch', 'cyan');
137+
138+
const files = findPackageFiles();
139+
140+
if (files.length === 0) {
141+
log('⚠️ No files found to patch', 'yellow');
142+
log(
143+
' This might mean packages are not installed or using different structure',
144+
'yellow',
145+
);
146+
return;
147+
}
148+
149+
log(` Found ${files.length} files to check`, 'blue');
150+
151+
const results = files.map(patchFile);
152+
const successful = results.filter(Boolean).length;
153+
154+
log(''); // Empty line
155+
156+
if (successful === files.length) {
157+
log('🎉 All files patched successfully!', 'green');
158+
log(' Tailwind v4 should now work with Plasmo', 'green');
159+
} else {
160+
log(`⚠️ ${successful}/${files.length} files patched`, 'yellow');
161+
}
162+
163+
if (successful === 0) {
164+
log('💡 Try running: pnpm install && node scripts/patch-jiti.js', 'blue');
165+
}
166+
};
167+
168+
// Execute if run directly
169+
if (require.main === module) {
170+
main();
171+
}
172+
173+
module.exports = { main, patchFile, findPackageFiles };

src/popup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function IndexPopup() {
8484
},
8585
breakpoints: {
8686
values: {
87-
//copied from tailwind.config.js
87+
//copied from globals.css
8888
xs: 0,
8989
sm: 640,
9090
md: 768,

src/styles/globals.css

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,57 @@
1-
@import url('https://fonts.googleapis.com/css2?family=Bai+Jamjuree:wght@500;600;700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
1+
@import url('https://fonts.googleapis.com/css2?family=Bai+Jamjuree:wght@500;600;700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap')
2+
layer(base);
23

3-
@tailwind base;
4-
@tailwind components;
5-
@tailwind utilities;
4+
@import 'tailwindcss';
65

7-
* {
8-
box-sizing: border-box;
6+
/*If changing be sure to update in popup.tsx too*/
7+
@theme {
8+
--color-haiti: #090b2c;
9+
--color-persimmon-50: #ffe5de;
10+
--color-persimmon-100: #ffcabd;
11+
--color-persimmon-200: #ffb09d;
12+
--color-persimmon-300: #ff947e;
13+
--color-persimmon-400: #ff7760;
14+
--color-persimmon-500: #ff5743; /* brand accent, danger*/
15+
--color-persimmon-600: #d14a39;
16+
--color-persimmon-700: #a43d2e;
17+
--color-persimmon-800: #793025;
18+
--color-persimmon-900: #51231b;
19+
--color-royal: #573dff; /* brand secondary (dark)*/
20+
--color-royal-dark: #3c2ab2;
21+
--color-cornflower-50: #eae4ff;
22+
--color-cornflower-100: #d3caff; /* ~periwinkle*/
23+
--color-cornflower-200: #bcb0fe;
24+
--color-cornflower-300: #a297fd;
25+
--color-cornflower-400: #857efc;
26+
--color-cornflower-500: #6266fa; /* brand primary*/
27+
--color-cornflower-600: #5455cc;
28+
--color-cornflower-700: #45449f; /* ~royal*/
29+
--color-cornflower-800: #363475;
30+
--color-cornflower-900: #28254d;
31+
--color-periwinkle: #c2c8ff; /* brand secondary (light)*/
32+
--color-shade: #101828; /* drop shadow color from shipfaster ui*/
33+
34+
--font-display: Bai Jamjuree, Roboto, sans-serif;
35+
--font-main: Inter, Roboto, sans-serif;
936
}
1037

11-
@layer base {
12-
html,
13-
body {
14-
@apply font-main;
15-
}
38+
@utility bg-lighten {
39+
background-color: rgba(255, 255, 255, 0.6);
40+
}
41+
42+
@utility bg-darken {
43+
background-color: rgba(0, 0, 0, 0.6);
1644
}
1745

1846
@layer utilities {
19-
.bg-lighten {
20-
background-color: rgba(255, 255, 255, 0.6);
47+
* {
48+
box-sizing: border-box;
2149
}
22-
.bg-darken {
23-
background-color: rgba(0, 0, 0, 0.6);
50+
}
51+
52+
@layer base {
53+
html,
54+
body {
55+
@apply font-main;
2456
}
2557
}

src/tabs/permissions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function PermissionsPls() {
5151
variant="contained"
5252
disableElevation
5353
size="large"
54-
className="normal-case bg-royal hover:bg-royalDark"
54+
className="normal-case bg-royal hover:bg-royal-dark"
5555
onClick={async () => {
5656
const response = await realBrowser.permissions.request({
5757
origins: neededOrigins,

tailwind.config.js

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)