peterwangsc/tailwint
GitHub: peterwangsc/tailwint
基于官方语言服务器的 Tailwind CSS linter,检测 class 冲突和规范化问题并支持自动修复。
Stars: 6 | Forks: 0
tailwind + lint = tailwint ~≈∼〜 一个针对 Tailwind CSS 的微型 linter
与 VS Code 显示的诊断信息相同——但通过命令行运行。检测 class 冲突,建议规范化重写,并自动修复所有问题。由官方 `@tailwindcss/language-server` 驱动——而非自定义解析器或正则技巧。 **支持 Tailwind CSS v4。** ## 检测内容 tailwint 检测两类问题: **⚡ 冲突** —— 应用相同 CSS 属性的 class,后者生效,前者成为死代码: ``` ⚡ 3:21 conflict 'w-full' applies the same CSS properties as 'w-auto' ⚡ 3:28 conflict 'w-auto' applies the same CSS properties as 'w-full' ``` **○ 规范** —— 可以以更短或更符合惯例的形式编写的 class: ``` ○ 3:21 canonical The class `flex-shrink-0` can be written as `shrink-0` ○ 3:35 canonical The class `z-[1]` can be written as `z-1` ○ 3:41 canonical The class `min-w-[200px]` can be written as `min-w-50` ``` ## 安装 ``` npm install -D tailwint @tailwindcss/language-server ``` ## 用法 ``` # 扫描默认文件类型 (tsx, jsx, html, vue, svelte, astro, mdx, css) npx tailwint # 扫描特定文件 npx tailwint "src/**/*.tsx" # 自动修复所有问题 npx tailwint --fix npx tailwint -f # 修复特定文件 npx tailwint --fix "app/**/*.tsx" # 详细 LSP 日志 DEBUG=1 npx tailwint ``` ## 示例输出 ``` ~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈~ tailwint ~∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼~ tailwind css linter // powered by the official lsp ✔ language server ready ~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~ ✔ sent 42 files to lsp ~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~~ ✔ 42/42 files received ~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~≈∼〜~~ 42 files scanned // 8 conflicts │ 12 canonical ┌ components/Card.tsx (3) ⚡ 5:21 conflict 'w-full' applies the same CSS properties as 'w-auto' ○ 5:35 canonical The class `flex-shrink-0` can be written as `shrink-0` ○ 5:49 canonical The class `z-[1]` can be written as `z-1` └~≈∼ ≈∼〜~≈ ✘ FAIL 20 issues in 3 files 2.1s ≈∼〜~≈ run with --fix to auto-fix ``` 使用 `--fix`: ``` ⚙ FIX conflicts first, then canonical ✔ ┃━━━━━━━━━━━━━━━━━━┃ Card.tsx 3 fixed ✔ ┃━━━━━━━━━━━━━━━━━━┃ Header.tsx 12 fixed ✔ ┃━━━━━━━━━━━━━━━━━━┃ Sidebar.tsx 5 fixed ≈∼〜~≈ ✔ FIXED 20 of 20 issues across 3 files 3.4s ≈∼〜~≈ ``` ## 支持的文件类型 | 扩展名 | 语言 ID | 备注 | | --------- | --------------- | ----------------------------------------- | | `.tsx` | typescriptreact | React / Next.js 组件 | | `.jsx` | javascriptreact | React 组件 | | `.html` | html | 静态 HTML 文件 | | `.vue` | html | Vue 单文件组件 | | `.svelte` | html | Svelte 组件 | | `.astro` | html | Astro 组件 | | `.mdx` | mdx | MDX 文档 | | `.css` | css | `@apply` 指令和 Tailwind at-rules | ## Tailwind v4 支持 tailwint 完全支持 Tailwind CSS v4 功能: - **不透明度简写** —— `bg-red-500/50`, `text-blue-500/75` - **`size-*` 工具类** —— `size-10`, `size-full` - **容器查询** —— `@container`, `@lg:flex`, `@md:grid` - **`has-*` / `not-*` 变体** —— `has-checked:bg-blue-500`, `not-disabled:opacity-100` - **`aria-*` 变体** —— `aria-expanded:bg-blue-500`, `aria-disabled:opacity-50` - **`data-*` 变体** —— `data-[state=open]:bg-blue-500` - **`supports-*` 变体** —— `supports-[display:grid]:grid` - **`forced-colors` 变体** —— `forced-colors:bg-[ButtonFace]` - **逻辑属性** —— `ms-4`, `me-4`, `ps-4`, `pe-4` - **文本换行工具类** —— `text-balance`, `text-pretty`, `text-nowrap` - **命名组/peer** —— `group/sidebar`, `group-hover/sidebar:bg-blue-500` - **CSS-first 配置** —— 带有 `@theme` 指令的 `@import "tailwindcss"` ## 编程 API ``` import { run } from "tailwint"; const exitCode = await run({ patterns: ["src/**/*.tsx"], fix: true, cwd: "/path/to/project", }); ``` ### 选项 | 选项 | 类型 | 默认值 | 描述 | | ---------- | ---------- | -------------------------------------------------- | -------------------------------------------- | | `patterns` | `string[]` | `["**/*.{tsx,jsx,html,vue,svelte,astro,mdx,css}"]` | 要扫描的文件的 Glob 模式 | | `fix` | `boolean` | `false` | 使用 LSP 代码操作自动修复问题 | | `cwd` | `string` | `process.cwd()` | 用于 glob 解析和 LSP 根目录的工作目录 | ### 导出 | 导出 | 描述 | | ---------------------------- | -------------------------------- | | `run(options?)` | 运行 linter,返回退出码 | | `applyEdits(content, edits)` | 将 LSP 文本编辑应用到字符串 | | `TextEdit` | LSP 文本编辑的 TypeScript 类型 | ## CI 集成 tailwint 为 CI 流水线提供有意义的退出码: | 退出码 | 含义 | | --------- | ---------------------------------------------------------------- | | `0` | 未发现问题,或使用 `--fix` 修复了所有问题 | | `1` | 发现问题,或使用 `--fix` 后仍有无法修复的问题 | | `2` | 致命错误(未找到语言服务器,崩溃) | ### GitHub Actions ``` - name: Lint Tailwind classes run: npx tailwint ``` ### Pre-commit hook ``` npx tailwint --fix && git add -u ``` ## 工作原理 1. **启动** —— 通过 stdio 生成 `@tailwindcss/language-server` 2. **预扫描** —— 对 CSS 文件进行分类,以预测服务器将创建多少个 Tailwind 项目,跳过不相关的 CSS 文件 3. **打开** —— 通过 `textDocument/didOpen` 将匹配的文件发送到服务器 4. **分析** —— 等待 `textDocument/publishDiagnostics` 通知(事件驱动,项目感知——分别跟踪每个项目的初始化和诊断) 5. **报告** —— 收集诊断信息,分类为冲突或规范化 6. **修复** _(如果 `--fix`)_ —— 请求 `textDocument/codeAction` 快速修复并循环应用编辑,直到没有诊断信息为止 修复循环是无限制的——它会持续应用编辑直到文件稳定。单次传递可能无法解决所有问题(例如,修复冲突可能会揭示底层的规范化问题),因此只要编辑产生更改,循环就会继续。 ## 环境要求 - Node.js 18+ - `@tailwindcss/language-server` >= 0.14.0 (peer dependency) ## 许可证 MIT标签:CSS优化, DNS解析, GNU通用公共许可证, Lint工具, LSP, MITM代理, Node.js, NPM包, OSV-Scalibr, Tailwind CSS, VS Code, 代码规范, 威胁情报, 开发者工具, 开源项目, 暗色界面, 死代码消除, 自动修复, 自动化攻击, 语言服务器协议, 错误基检测, 静态代码分析