-
Notifications
You must be signed in to change notification settings - Fork 2
refactor!: move to tailwind api utils, tailwind v4 support #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9d9dd89
to
f7ac36f
Compare
My boy takes initiative! 💖 |
Just came here to say thank you <3 |
亮神伟大,无须多言 ☝️ |
🫶 |
Where do you need to set the config path exactly? Trying to use this and not sure where to do that |
I think i found a way to resolve the tailwind config file, automatically. (if you want to build atop of it) -, the function does a "best effort" on finding a .css file with Im currently using this in a monorepo, and it works 👌 /**
* Recursively walks `dir`, looking for the first .css file
* that has a line starting with @import "tailwindcss
* @param {string} dir absolute path to start searching from
* @returns {string|null} absolute path to matching CSS, or null if none found
*
* @example
* const twCssPath = findTailwindImportCss(process.cwd())
*/
function findTailwindImportCss(dir) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const found = findTailwindImportCss(fullPath);
if (found) return found;
} else if (entry.isFile() && entry.name.endsWith(".css")) {
// read & scan lines
const lines = fs.readFileSync(fullPath, "utf8").split(/\r?\n/);
for (let line of lines) {
if (line.trim().startsWith('@import "tailwindcss')) {
return fullPath;
}
}
}
}
return null;
}
// usage:
export default [
...tailwindPlugin.configs["flat/recommended"],
{
settings: {
tailwindcss: {
config: findTailwindImportCss(process.cwd()), // <- uses process.cwd() to start looking down from where eslint is run
},
},
},
] |
@TheHanna here are the steps I followed on a Vite app: On On
@kddige that worked great! In my case setting the relative path of |
If all sounds good then publish a npm package named |
In general, this fork works with Tailwind 4, but there are still some issues. For example, the new class “isolate” is not recognized (no-custom-classname). The same applies to custom classes defined in the “@layer component” when they contain a hyphen (because the hyphen is used as a separator and the class name will be split). |
in my setup, the |
I use PNPM Workspaces + NX Monorepo and it fails to load Tailwind 4 for me. pnpm run lint:tailwind "./**/*.{js,jsx,ts,tsx}" --max-warnings 0
> ui@0.0.0 lint:tailwind D:\Work\new-engine\libs\ui
> eslint "**/*.{js,jsx,ts,tsx}" --config eslint.config.js "./**/*.{js,jsx,ts,tsx}" "--max-warnings" "0"
Oops! Something went wrong! :(
ESLint: 9.26.0
Error: Could not resolve tailwindcss
at TailwindUtils.loadConfigV4 (D:\Work\new-engine\node_modules\.pnpm\tailwind-api-utils@1.0.2_tailwindcss@4.1.6\node_modules\tailwind-api-utils\dist\index.cjs:391:13)
at TailwindUtils.loadConfig (D:\Work\new-engine\node_modules\.pnpm\tailwind-api-utils@1.0.2_tailwindcss@4.1.6\node_modules\tailwind-api-utils\dist\index.cjs:381:18)
at D:\Work\new-engine\node_modules\.pnpm\@hyoban+eslint-plugin-tailw_35146946690b35920ea77267a21f7779\node_modules\@hyoban\eslint-plugin-tailwindcss\lib\util\getTailwindConfigWorker.js:7:25
at D:\Work\new-engine\node_modules\.pnpm\synckit@0.11.8\node_modules\synckit\lib\index.cjs:517:20
at MessagePort.<anonymous> (D:\Work\new-engine\node_modules\.pnpm\synckit@0.11.8\node_modules\synckit\lib\index.cjs:539:5)
at [nodejs.internal.kHybridDispatch] (node:internal/event_target:827:20)
at MessagePort.<anonymous> (node:internal/per_context/messageport:23:28)
ELIFECYCLE Command failed with exit code 2. |
yes, it also breaks the auto close tag rule |
👋 @hyoban and thank you for you work, I started working on a full rewrite of the plugin few months ago but I was stuck when trying to load the config from TW4 as it is done in async while eslint only accepts synchronous code. Glad to browse your PR. I'll update few on my main projects to TW4 and see how your version handles it. IMO, the v4 release should only support TW4, the projects using TW4 should stick with eslint-plugin-tailwindcss v3... 👏 |
@francoismassart, I'm glad you found some time to look back at eslint-plugin-tailwindcss. Thank you so much for your work. My fork has only some minor changes to make it work with the basics of Tailwind v4. I haven't tested it extensively yet, so it may still have some issues, and I'd be happy to fix them based on feedback. I have no problem with the new version of eslint-plugin-tailwindcss only supporting tailwind v4, which can reduce the cost of maintenance. |
Speaking of newer version, how hard would it be for you to support other linters like Oxlint or Biome? 😊 |
Biome has an integrated rule for class sorting |
That's great, I'm looking for invalid tailwind classes. We base everything on Tailwind, so I want to ban invalid classes all together. :) Right now I use TW4 version of this plugin (which works great BTW, great job!). |
Sorry, I'm not familiar with Biome and unless we start using it at work, I don't think I'll work on that. But if I was coding it, I would use the same logic as in this PR: don't reinvent the wheel and delegate the business logic (sorting/validating class as Tailwind CSS, etc.) to the existing methods provided by the tailwindcss package itself. |
@hyoban
|
All versions of eslint 8 have been marked as deprecated, so I think this should be a minor issue? |
@hyoban do you mean we should release Tailwind CSS v4 support with ESLint at min v9 ? |
I noticed a first issue with the
I can still get the error shown by a third party rule (cssConflict) but the eslint-plugin-tailwindcss does not get the 2nd case... |
Another issue I've met, if you use There is no But the |
Strange, the issue did disappeared, maybe it was due to some internal mechanics of NX monorepo... |
@hyoban, here what I plan to do:
Could you edit this PR and mark it as ready for release ? Thank you for your help, it is greatly appreciated. |
Thanks a lot, I will create a PR |
Close to prefer francoismassart#413 |
On my main projects we are using a monorepo and pipelines which run tests in their own context/setup. Passing an hardcoded path pointing to the CSS config for the plugin is not possible nor ideal for us. But here is how we fixed it:
import { dirname } from 'path'
import { fileURLToPath } from 'url'
...
{
settings: {
tailwindcss: {
config: dirname(fileURLToPath(import.meta.url)) + '/apps/site/styles/tailwind.css',
... |
Try today?
You can also use an alias to keep the dependency name. If we can merge the changes upstream, then you can remove the alias.
Get the latest alpha version on npm.
For v4, you need to set the config path manually.