12 changed files with 98 additions and 39 deletions
@ -0,0 +1,45 @@ |
|||||
|
import type { Plugin } from 'vite'; |
||||
|
|
||||
|
interface CssLayerRule { |
||||
|
/** 层名,需在 css 中先于 @import 'tailwindcss' 声明层顺序(见 internal/tailwind-config/theme.css) */ |
||||
|
layerName: string; |
||||
|
/** 需要包层的包名(匹配该包在 node_modules 下的 css 模块 id) */ |
||||
|
packageName: string; |
||||
|
} |
||||
|
|
||||
|
function escapeRegExp(value: string): string { |
||||
|
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 把指定包内的 css 包进 @layer: |
||||
|
* 组件库的 css 是无层样式,无层样式在级联中永远压过 @layer 内的 Tailwind 工具类; |
||||
|
* 包层后由 theme.css 的层声明决定顺序(utilities 排在组件库层之后), |
||||
|
* 使 Tailwind 工具类可以覆盖组件库样式。 |
||||
|
* |
||||
|
* @example |
||||
|
* ```ts
|
||||
|
* plugins: [viteCssLayerPlugin({ packageName: 'element-plus', layerName: 'el' })] |
||||
|
* ``` |
||||
|
*/ |
||||
|
export function viteCssLayerPlugin( |
||||
|
rules: CssLayerRule | CssLayerRule[], |
||||
|
): Plugin { |
||||
|
const list = Array.isArray(rules) ? rules : [rules]; |
||||
|
const matchers = list.map(({ layerName, packageName }) => ({ |
||||
|
layerName, |
||||
|
regex: new RegExp(`${escapeRegExp(packageName)}[\\\\/].+\\.css$`, 'i'), |
||||
|
})); |
||||
|
return { |
||||
|
name: 'vite-plugin-css-layer', |
||||
|
enforce: 'pre', |
||||
|
transform(code, id) { |
||||
|
const [file] = id.split('?', 1); |
||||
|
if (!file) return; |
||||
|
const matched = matchers.find((m) => m.regex.test(file)); |
||||
|
if (matched) { |
||||
|
return { code: `@layer ${matched.layerName} {\n${code}\n}`, map: null }; |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
} |
||||
Loading…
Reference in new issue