@antebudimir/eslint-plugin-vanilla-extract

中文文档
2.0.0发布于 2026/11/01MITTypeScriptES Module近 30 天下载 4.8万

综合ESLint插件,用于有 CSS 财产订单的香草-提取,样式验证,以及最佳做法执行. 支持字母顺序,同心和自定义的 CSS 命令,自动固定,以及零运行时的安全性.

中文使用文档
文档目录32 节
  1. 演示
  2. 特征
  3. 所需资源
  4. 安装
  5. 使用量
  6. 配置选项
  7. 备选案文1:使用扩展(建议,可从v1.1.0.0获得)
  8. 备选案文2:使用带有明确规则的插件
  9. 使用FlatCompat(用于ESLint 8.57.0和8.57.1)
  10. VS 代码整合
  11. 建议配置
  12. 自定义配置
  13. 全球设置( 建议用于共享包装)
  14. 规则
  15. 香草-抽取/止痛-顺序
  16. 香草-提取/同心-顺序
  17. 香草-抽取/海关订单
  18. 香草-取出/无空-风格-块
  19. 香草-抽取/无px-单位
  20. 香草-提取/无拖动-零
  21. 香草-抽取/无单位值
  22. 香草-抽取/无名单位
  23. 香草-抽取/零单位
  24. 香草-摘录/优先逻辑-财产
  25. 香草-摘录/预选主题
  26. 字体面部声明
  27. 同心CSS模型
  28. 路线图
  29. 已完成的里程碑
  30. 即将到来的特点
  31. 捐款
  32. 许可证

@antebudimir/eslint-plugin-vanilla-extract (英语)

CI Coverage Status npm version NPM Downloads


保持这个插件需要时间和小心! 如果你认为它很有价值,请考虑支持它的发展:
GitHub赞助商: https://github.com/赞助商/antebudimir 互联网档案馆的存檔,存档日期2013-12-21
☕: https://ko-fi.com/antebudimir (英语)
* 革命: https://revolut.me/antebudimir 页面存档备份,存于互联网档案馆
自由报: https://liberapay.com/antebudimir 页面存档备份,存于互联网档案馆


用于香草取材的 ESLint 综合插件,用于执行其中的最佳做法 香草摘录 CSS风格. 包括支助CSS财产订购(麻痹, 同心圆),和自定义组顺序),高级样式林出规则,自动固定,并验证了香草-取材所特有的样式图案. 确保零运行时间安全,并与多个香草抽取的API相融合,以促进各项目之间可维护、一致的代码

演示

Plugin Demo

特征

  • 执行 CSS 属性命令 :
    • 按字母顺序排列的干净、可预测的风格组织
    • 逻辑、外部财产安排的同心命令
  • 自定义组命令更多精细控件的选项
  • 与 ESLint 8.57.0+, 9.x 和 10.x (平面配置)相兼容
  • 提供自动排序属性的自动固定能力
  • 处理多组香草-取出 API(样式,样式变异,配方,全球Style等)
  • 处理嵌入对象、样式阵列和伪选择器等复杂案件
  • 与 vanilla- extract 中使用的 Case 属性有关的工作
  • 提高代码质量的其他规则(见即将出现的特性路线图)
  • 自动包装器函数检测 - 使用自定义的包装器函数调用 vanilla-extract API 引用跟踪以应用所有规则,无论香草-提取函数是如何包裹的

所需资源

  • ESLint 8.57.0或以上(8.57、9.x和10.x都得到支持和测试)
  • 20.19.0或以上的节点
  • 无害环境管理(ECMAScript模块)
  • 使用任意一种的平面配置系统 :
    • eslint.config.mjs (建议,总是与无害环境管理插件合作)
    • eslint.config.js (除非你的包裹.json已经) "type": "module"(中文(简体) )

ESLint 10用户的说明: 如果您同时使用 typescript-eslint,确保你在 typescript-eslint QQ 8.46 (首次发布声明ESLint 10支持)以避免 相互依赖的冲突.

安装

# Using npm
npm install --save-dev @antebudimir/eslint-plugin-vanilla-extract

# Using yarn
yarn add --dev @antebudimir/eslint-plugin-vanilla-extract

# Using pnpm
pnpm add -D @antebudimir/eslint-plugin-vanilla-extract

# For ESLint 8.57.0 with flat config, you'll also need:
npm install --save-dev @eslint/eslintrc @eslint/js
yarn add --dev @eslint/eslintrc @eslint/js
pnpm add -D @eslint/eslintrc @eslint/js

使用量

注:此插件仅限无害环境管理. 它必须使用无害环境管理配置,不能使用通用JS require()。 。 。 .

配置选项

您的 ESLint 平面配置中有两种主要配置插件的方法:

适用建议规则的最简单和最简洁的方式:

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    ignores: ['src/**/theme-contract.css.ts'],
    extends: [vanillaExtract.configs.recommended],
    // You can still override rules when using extends
    // rules: {
    //   'vanilla-extract/concentric-order': 'off',
    //   'vanilla-extract/alphabetical-order': 'error',
    // },
  },
];

备选案文2:使用带有明确规则的插件

这种方法更加明确 - 您手动注册插件并传播推荐的规则 :

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    ignores: ['src/**/theme-contract.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    rules: {
      // Apply all recommended rules
      ...vanillaExtract.configs.recommended.rules,

      // Optionally override specific rules
      // 'vanilla-extract/concentric-order': 'warn', // Change severity from error to warn
      // 'vanilla-extract/no-empty-style-blocks': 'off', // Disable a recommended rule
      // 'vanilla-extract/no-zero-unit': 'warn', // Change severity from error to warn

      // Switch to a different ordering rule (see "Important" section below)
      // 'vanilla-extract/concentric-order': 'off',
      // 'vanilla-extract/alphabetical-order': 'error',
    },
  },
];

重要: 一次只启用一个顺序规则

插件包括三个CSS属性订购规则: alphabetical-order, (中文(简体) ), concentric-order,以及 custom-order。 。 。 . 一次只允许一个命令规则 以避免自定义冲突.

如果您想要使用与推荐配置中的规则不同的顺序规则, 您必须明确禁用默认规则 .

示例:从同心圆切换到字母顺序
export default [
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    rules: {
      ...vanillaExtract.configs.recommended.rules,
      'vanilla-extract/concentric-order': 'off',      // Disable the default
      'vanilla-extract/alphabetical-order': 'error',  // Enable alphabetical
    },
  },
];
export default [
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    rules: {
      ...vanillaExtract.configs.recommended.rules,
      'vanilla-extract/concentric-order': 'off',  // Disable the default
      'vanilla-extract/custom-order': [
        'error',
        {
          groupOrder: ['font', 'dimensions', 'margin', 'padding', 'position', 'border'],
          sortRemainingProperties: 'alphabetical',
        },
      ],
    },
  },
];

QQ 警告 : 如果同时启用多条订购规则,它们会生成ESLint无法应用的相冲突自定义,导致自定义被保存失败. 总是确保只有一个命令规则有效 .

使用FlatCompat(用于ESLint 8.57.0和8.57.1)

如果你从遗留的ESLint配置中迁移出去,你可以使用 FlatCompat 用于在添加时转换它们 香草-提取支持 :

import path from 'path';
import { fileURLToPath } from 'url';
import { FlatCompat } from '@eslint/eslintrc';
import js from '@eslint/js';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

// Mimic CommonJS variables
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Create a compatibility layer instance
const compat = new FlatCompat({
  baseDirectory: __dirname,
  recommendedConfig: js.configs.recommended,
});

export default [
  // Convert your existing ESLint configs
  ...compat.config({
    extends: [
      'eslint:recommended',
      'plugin:@typescript-eslint/recommended',
      // etc
    ],
  }),

  // Add vanilla-extract by using explicit rule config
  {
    files: ['**/*.css.ts'],
    ignores: ['src/**/theme-contract.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    rules: {
      // Apply all recommended rules
      ...vanillaExtract.configs.recommended.rules,
      // or specify rule by rule as described above
    },
  },
];

与平面兼容的常见问题

  1. 错误: “ 意外的顶层属性“ 文件 ”

    • 解决方案: 当使用时 compat.config(),使用时 overrides 改为 files 在顶层.
  2. 错误: FlatCompat 构造器中“ 缺少参数“ 建议的Config”

    • 解决方案:导入 js 从 @eslint/js 添加 recommendedConfig: js.configs.recommended 切换到平面 建筑师.
  3. 错误 : “ 在用户定义的索引 0 下未定义的配置 ”

    • 解决方案:确保您在配置阵列中使用默认导出.

VS 代码整合

用于 VS 代码用户,将这些设置添加到您的 .vscode/settings.json数字 :

{
  "eslint.useFlatConfig": true,
  "eslint.experimental.useFlatConfig": true,
  "eslint.validate": ["javascript", "typescript", "typescriptreact"]
}

推荐的配置可以使以下规则具有出错的严重程度:

  • vanilla-extract/concentric-order执行 同心圆 CSS 属性排序
  • vanilla-extract/no-empty-style-blocks: 防止空样式块
  • vanilla-extract/no-trailing-zero: 取消在数值 CSS 中以 0 为后缀
  • vanilla-extract/no-unknown-unit:禁止使用未识别的CSS单元
  • vanilla-extract/no-zero-unit: 删除零值不必要的单位

可用的其他规则 (默认无法启用) :

  • vanilla-extract/alphabetical-order: 备选顺序规则(平分)
  • vanilla-extract/custom-order: 备选排序规则(基于海关集团的排序)
  • vanilla-extract/no-px-unit: 取消带有可选允许列表的 px 单位
  • vanilla-extract/no-unitless-values: 取消 CSS 属性需要单位的单位值
  • vanilla-extract/prefer-logical-properties: 在物理方向属性上执行逻辑 CSS 属性
  • vanilla-extract/prefer-theme-tokens: 执行主题符而不是硬码值, 用于颜色、 间隔、 字体大小、 边框半径、 边框宽度、 阴影、 z- 索引、 不透明、 字体权重、 过渡/ 动画( 可选择评价助手函数和模板字节)

您可以使用推荐的配置作为起点, 并根据您的项目需要推翻规则 。 参见上面关于如何在命令规则之间切换的配置示例.

自定义配置

如果您不愿使用推荐的配置, 您仍然可以手动配置规则 :

export default [
  {
    files: ['**/*.css.ts'],
    ignores: ['src/**/theme-contract.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    rules: {
      // 'vanilla-extract/alphabetical-order': 'warn',
      // OR
      // 'vanilla-extract/concentric-order': 'warn',
      // OR
      'vanilla-extract/custom-order': [
        'warn',
        {
          groupOrder: ['font', 'dimensions', 'margin', 'padding', 'position', 'border'], // example group order
          // optional
          sortRemainingProperties: 'concentric', // 'alphabetical' is default
        },
      ],
      'vanilla-extract/no-unknown-unit': 'error',
      'vanilla-extract/no-zero-unit': 'warn',
    },
  },
];

说明: 记住每次只允许一个命令规则 。 关于订购规则之间的切换细节见上文"重要"部分.

如果使用跨越多条顺序规则的导入的包装器函数,请在 ESLint 中配置一次 settings。 。 。 . 所有订购规则( E)alphabetical-order, (中文(简体) ), concentric-order, (中文(简体) ), custom-order)读取此值.

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    settings: {
      'vanilla-extract': {
        style: ['componentStyle', 'layerStyle'],
        recipe: ['componentRecipe'],
      },
    },
    rules: {
      ...vanillaExtract.configs.recommended.rules,
    },
  },
]);

仅通过 ESLint 配置包装名 settings (单位:千美元)style, (中文(简体) ), recipe) (中文(简体) ).

规则

香草-抽取/止痛-顺序

此规则强制要求 香草- extract 样式对象的 CSS 属性遵循字母顺序 .

// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  display: 'flex',
  justifyContent: 'center',
  alignItems: 'center',
  height: 19,
  marginBottom: 1,
  marginLeft: 2,
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  alignItems: 'center',
  display: 'flex',
  height: 19,
  justifyContent: 'center',
  marginBottom: 1,
  marginLeft: 2,
});

字母顺序的全局设置 : settings['vanilla-extract'].style

vanilla-extract/alphabetical-order 从 Global ESLint 设置中读取包裹名称.

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    settings: {
      'vanilla-extract': {
        style: ['componentStyle'],
      },
    },
    rules: {
      'vanilla-extract/alphabetical-order': 'error',
    },
  },
]);

香草-提取/同心-顺序

此规则强制要求 香草- extract 样式对象遵循 CSS 属性 同心圆 CSS 命令模式,将属性从外部组织到内部.

// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  color: 'red',
  display: 'flex',
  position: 'relative',
  padding: '10px',
  margin: '20px',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  position: 'relative',
  display: 'flex',
  margin: '20px',
  padding: '10px',
  color: 'red',
});

同心圆顺序的全局设置 : settings['vanilla-extract'].style

从本地模块导入样式包装时使用此设置( 例如) componentStyle, (中文(简体) ), layerStyle) (中文(简体) ). 如果列出一个折叠函数名称,则规则处理调用该函数的方式如下: style(...) 打电话.

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    settings: {
      'vanilla-extract': {
        style: ['componentStyle', 'layerStyle'],
      },
    },
    rules: {
      'vanilla-extract/concentric-order': 'error',
    },
  },
]);

香草-抽取/海关订单

这个 vanilla-extract/custom-order 规则允许您执行 CSS 属性自定义命令 香草-取材风格. 您可以按首选顺序指定一系列属性组, 该规则将保证 这些群体中的财产按其在 同心CSS模型。 。 。 .

这一规则的主要特点包括:

  1. 自定义组排序 : 定义 CSS 属性组的首选顺序 .
  2. 未指定组的处理: 自定义数组中未包含的所有组,其属性排序如下 最后一个指定组.
  3. 灵活排序选项:您可以选择按字母排序或按字母排序其余属性 设置 CSS 顺序 sortRemainingProperties 选项为“同心”或“同心”.

默认行为 :

  • 如果没有设定, sortRemainingProperties 默认为“ alphabetic” .
  • 若无 groupOrder 指定或提供空数组,规则将默认排序所有属性 按字母顺序排列 sortRemainingProperties 即使设定了也会被忽略.

要配置规则,请将规则添加到您的 ESLint 配置文件中,并附上您想要的选项 。 您可以自定义 groups 数组包括您想要执行的任何可用的 CSS 属性组, 至少包含一个组 所需经费.

自定义顺序的全球设置 : settings['vanilla-extract'].style

vanilla-extract/custom-order 也读作 style 从全球环境与 groupOrder 财务报告和审定财务报表 sortRemainingProperties。 。 。 .

import { defineConfig } from 'eslint/config';
import vanillaExtract from '@antebudimir/eslint-plugin-vanilla-extract';

export default defineConfig([
  {
    files: ['**/*.css.ts'],
    plugins: {
      'vanilla-extract': vanillaExtract,
    },
    settings: {
      'vanilla-extract': {
        style: ['componentStyle'],
      },
    },
    rules: {
      'vanilla-extract/custom-order': [
        'error',
        {
          groupOrder: ['font', 'dimensions', 'margin', 'padding', 'position', 'border'],
          sortRemainingProperties: 'alphabetical',
        },
      ],
    },
  },
]);
// ❌ Incorrect (Unordered)
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  color: 'blue',
  padding: '10px',
  fontFamily: 'Arial, sans-serif',
  margin: '20px',
  width: '200px',
  border: '1px solid black',
  display: 'flex',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  // font group
  fontFamily: 'Arial, sans-serif',
  color: 'blue',

  // dimensions group
  width: '200px',

  // margin group
  margin: '20px',

  // padding group
  padding: '10px',

  // display group
  display: 'flex',

  // border group
  border: '1px solid black',
});

香草-取出/无空-风格-块

此规则在 vanilla-extract 样式表中检测并预防空样式块. 它有助于维护更清洁的密码库 取消由于不完全重构或被遗忘的执行而产生的空样式定义.

// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const emptyStyle = style({});

export const nestedEmpty = style({
  color: 'blue',

  ':hover': {},
  '@media': {
    '(min-width: 768px)': {},
  },
});

export const recipeWithEmptyVariants = recipe({
  base: { color: 'black' },
  variants: {},
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const nestedEmpty = style({
  color: 'blue',
});

export const recipeWithEmptyVariants = recipe({
  base: { color: 'black' },
});

自动固定安全

规定只有在安全时才能自动转移声明. 声明是: 未报告 自动修正 (你必须手动解决)

  • 声明 导出 (单位:千美元)export const x = style({})——出口标识符可被进口 用作一种 className 在其它文件中,规则无法看到.
  • 标识符的 仍在同一文件中的其他地方引用 ——例如,作为类名钩子在a globalStyle() 选择器模板文字 :
// ❌ Reported, but not auto-fixed (the identifier's still referenced)
import { globalStyle, style } from '@vanilla-extract/css';

// used only as a class-name hook, not for its own props
export const buttonWrapper = style({});

globalStyle(`${buttonWrapper} > svg`, {
  color: 'red',
});

宣告无标识符的空块( 如 . globalStyle('ul', {}))和无参考、无出口 声明仍然完全可自动固定.

如果有意使用空声明作为类名钩,而根本不希望报告,则启用 ignoreReferenced 选项 :

选项

选项类型默认说明
ignoreReferencedbooleanfalse不要报告被导出或仍在他处引用的空样式声明(如故意类名钩).
{
  "rules": {
    "vanilla-extract/no-empty-style-blocks": ["error", { "ignoreReferenced": true }]
  }
}

真正的未使用的空声明仍然被报告,并随此选项自动删除. 财产一级探测 (空选者, @media编号 :@supports 对象,空变位值等)也保持活性——只有 出口/参考申报的完整申报报告被删除.

香草-抽取/无px-单位

此规则不允许使用硬码 px 以香草-取材样式申报的单位。 偏爱 rem, (中文(简体) ), em,或主题符号。 配置允许列表允许您使用特定属性 px 必要时。 允许列表支持 CameCase 和 kebab 大小写属性名称 .

带有允许列表的配置 :

{
  "rules": {
    "vanilla-extract/no-px-unit": ["error", { "allow": ["borderWidth", "outline-offset"] }]
  }
}

在此之前:

import { style } from '@vanilla-extract/css';

export const box = style({
  marginTop: '8px',
  padding: '16px',
  selectors: {
    '&:hover': { gap: '4px' },
  },
});

在(建议用雷姆显示的固定)之后:

import { style } from '@vanilla-extract/css';

export const box = style({
  marginTop: '8rem',
  padding: '16rem',
  selectors: {
    '&:hover': { gap: '4rem' },
  },
});

香草-提取/无拖动-零

此规则不允许在 vanilla- extract 样式对象中, 在数字 CSS 值中排入零 。 它有助于保持清洁 和更加一致的CSS,从小数中去除不必要的后缀零.

// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  margin: '1.0px',
  padding: '2.50rem',
  opacity: 1.0,
  lineHeight: 2.50,
  width: '0.0em',
  transition: 'all 0.30s ease',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  margin: '1px',
  padding: '2.5rem',
  opacity: 1,
  lineHeight: 2.5,
  width: '0',
  transition: 'all 0.3s ease',
});

香草-抽取/无单位值

此规则不允许 CSS 属性的单位数字值, 这些属性需要 vanilla-extract 样式对象中的单位 。 它帮助偏爱显性单位的团队避免混淆,因为香草-取出会自动将无单位数字转换为: px 在运行时间.

说明: 这是一个可选规则(在推荐配置中未启用). 只有当您的团队更喜欢清晰的单位 而不是香草的自动复制时, 才能启用它 px 转换.

带有允许属性的配置 :

{
  "rules": {
    "vanilla-extract/no-unitless-values": ["warn", { "allow": ["width", "height"] }]
  }
}
// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  width: 100,
  margin: 20,
  padding: 10.5,
  height: '50',
  top: '-10',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  width: '100px',
  margin: '20px',
  padding: 0,
  height: '50rem',
  opacity: 0.5,      // opacity accepts unitless values
  lineHeight: 1.5,   // line-height accepts unitless values
  zIndex: 10,        // z-index accepts unitless values
});

需要单位属性 :

  • 框型号 : width, (中文(简体) ), height, (中文(简体) ), minWidth, (中文(简体) ), maxWidth, (中文(简体) ), minHeight, (中文(简体) ), maxHeight, (中文(简体) ), min-width, (中文(简体) ), max-width, (中文(简体) ), min-height, (中文(简体) ), max-height
  • 间距 : margin, (中文(简体) ), marginTop, (中文(简体) ), marginRight, (中文(简体) ), marginBottom, (中文(简体) ), marginLeft, (中文(简体) ), marginBlock, (中文(简体) ), marginBlockStart, (中文(简体) ), marginBlockEnd, (中文(简体) ), marginInline, (中文(简体) ), marginInlineStart, (中文(简体) ), marginInlineEnd, (中文(简体) ), margin-top, (中文(简体) ), margin-right, (中文(简体) ), margin-bottom, (中文(简体) ), margin-left, (中文(简体) ), margin-block, (中文(简体) ), margin-block-start, (中文(简体) ), margin-block-end, (中文(简体) ), margin-inline, (中文(简体) ), margin-inline-start, (中文(简体) ), margin-inline-end, (中文(简体) ), padding, (中文(简体) ), paddingTop, (中文(简体) ), paddingRight, (中文(简体) ), paddingBottom, (中文(简体) ), paddingLeft, (中文(简体) ), paddingBlock, (中文(简体) ), paddingBlockStart, (中文(简体) ), paddingBlockEnd, (中文(简体) ), paddingInline, (中文(简体) ), paddingInlineStart, (中文(简体) ), paddingInlineEnd, (中文(简体) ), padding-top, (中文(简体) ), padding-right, (中文(简体) ), padding-bottom, (中文(简体) ), padding-left, (中文(简体) ), padding-block, (中文(简体) ), padding-block-start, (中文(简体) ), padding-block-end, (中文(简体) ), padding-inline, (中文(简体) ), padding-inline-start, (中文(简体) ), padding-inline-end
  • 位置设置 : top, (中文(简体) ), right, (中文(简体) ), bottom, (中文(简体) ), left, (中文(简体) ), inset, (中文(简体) ), insetBlock, (中文(简体) ), insetBlockStart, (中文(简体) ), insetBlockEnd, (中文(简体) ), insetInline, (中文(简体) ), insetInlineStart, (中文(简体) ), insetInlineEnd, (中文(简体) ), inset-block, (中文(简体) ), inset-block-start, (中文(简体) ), inset-block-end, (中文(简体) ), inset-inline, (中文(简体) ), inset-inline-start, (中文(简体) ), inset-inline-end
  • 边框 : borderWidth, (中文(简体) ), borderTopWidth, (中文(简体) ), borderRightWidth, (中文(简体) ), borderBottomWidth, (中文(简体) ), borderLeftWidth, (中文(简体) ), borderBlockWidth, (中文(简体) ), borderBlockStartWidth, (中文(简体) ), borderBlockEndWidth, (中文(简体) ), borderInlineWidth, (中文(简体) ), borderInlineStartWidth, (中文(简体) ), borderInlineEndWidth, (中文(简体) ), border-width, (中文(简体) ), border-top-width, (中文(简体) ), border-right-width, (中文(简体) ), border-bottom-width, (中文(简体) ), border-left-width, (中文(简体) ), border-block-width, (中文(简体) ), border-block-start-width, (中文(简体) ), border-block-end-width, (中文(简体) ), border-inline-width, (中文(简体) ), border-inline-start-width, (中文(简体) ), border-inline-end-width, (中文(简体) ), borderRadius, (中文(简体) ), borderTopLeftRadius, (中文(简体) ), borderTopRightRadius, (中文(简体) ), borderBottomLeftRadius, (中文(简体) ), borderBottomRightRadius, (中文(简体) ), borderStartStartRadius, (中文(简体) ), borderStartEndRadius, (中文(简体) ), borderEndStartRadius, (中文(简体) ), borderEndEndRadius, (中文(简体) ), border-radius, (中文(简体) ), border-top-left-radius, (中文(简体) ), border-top-right-radius, (中文(简体) ), border-bottom-left-radius, (中文(简体) ), border-bottom-right-radius, (中文(简体) ), border-start-start-radius, (中文(简体) ), border-start-end-radius, (中文(简体) ), border-end-start-radius, (中文(简体) ), border-end-end-radius
  • 类型 : fontSize, (中文(简体) ), font-size, (中文(简体) ), letterSpacing, (中文(简体) ), letter-spacing, (中文(简体) ), wordSpacing, (中文(简体) ), word-spacing, (中文(简体) ), textIndent, (中文(简体) ), text-indent
  • 布局 : gap, (中文(简体) ), rowGap, (中文(简体) ), columnGap, (中文(简体) ), row-gap, (中文(简体) ), column-gap, (中文(简体) ), flexBasis, (中文(简体) ), flex-basis
  • 大纲 : outlineWidth, (中文(简体) ), outline-width, (中文(简体) ), outlineOffset, (中文(简体) ), outline-offset
  • 其他情况: blockSize, (中文(简体) ), inlineSize, (中文(简体) ), minBlockSize, (中文(简体) ), maxBlockSize, (中文(简体) ), minInlineSize, (中文(简体) ), maxInlineSize, (中文(简体) ), block-size, (中文(简体) ), inline-size, (中文(简体) ), min-block-size, (中文(简体) ), max-block-size, (中文(简体) ), min-inline-size, (中文(简体) ), max-inline-size

接受无单位值的属性 :

  • 常见 : opacity, (中文(简体) ), zIndex, (中文(简体) ), z-index, (中文(简体) ), lineHeight, (中文(简体) ), line-height, (中文(简体) ), flexGrow, (中文(简体) ), flex-grow, (中文(简体) ), flexShrink, (中文(简体) ), flex-shrink, (中文(简体) ), order, (中文(简体) ), fontWeight, (中文(简体) ), font-weight, (中文(简体) ), zoom
  • 动画: animationIterationCount, (中文(简体) ), animation-iteration-count
  • 布局 : columnCount, (中文(简体) ), column-count, (中文(简体) ), orphans, (中文(简体) ), widows
  • 网格 : gridColumn, (中文(简体) ), grid-column, (中文(简体) ), gridColumnEnd, (中文(简体) ), grid-column-end, (中文(简体) ), gridColumnStart, (中文(简体) ), grid-column-start, (中文(简体) ), gridRow, (中文(简体) ), grid-row, (中文(简体) ), gridRowEnd, (中文(简体) ), grid-row-end, (中文(简体) ), gridRowStart, (中文(简体) ), grid-row-start
  • SVG : (英语) fillOpacity, (中文(简体) ), fill-opacity, (中文(简体) ), strokeOpacity, (中文(简体) ), stroke-opacity, (中文(简体) ), strokeMiterlimit, (中文(简体) ), stroke-miterlimit

为什么用这个规则?

当香草-提取物安全地将单数转换为 px,一些团队更喜欢明确的单位,因为:

  1. 它使预定单位清晰(px, rem,em,%等)
  2. 它防止在选择雷姆或其他单位时意外使用px
  3. 它符合中央支助系统关于明确各单位的最佳做法

自动修补 : 不详。 由于不同的队伍更喜欢不同的单位(px,rem,em,%),所以您必须手动添加首选的单位.

香草-抽取/无名单位

此规则强制在香草-提取样式对象中使用有效的 CSS 单元. 防止打字和非标准单位 ,这可能造成样式问题或浏览器相容性问题.

// ❌ Incorrect
import { style, globalStyle, recipe } from '@vanilla-extract/css';

export const invalidStyle = style({
  margin: '5abc', // Non-existent unit
  fontSize: '1.5rems', // Typo in unit
});

export const myRecipe = recipe({
  variants: {
    size: {
      large: { padding: '4xm' }, // Invalid unit
    },
  },
});

// ✅ Correct
import { style, globalStyle, recipe } from '@vanilla-extract/css';

export const validStyle = style({
  margin: '5rem',
  fontSize: '1.5rem',
});

export const myRecipe = recipe({
  variants: {
    size: {
      large: { padding: '4em' },
    },
  },
});

香草-抽取/零单位

此规则强制删除香草-提取样式对象中零值的不必要的单位. 帮助维持 通过去除值为零的冗余单位来更清洁更一致的CSS.

// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  margin: '0px',
  padding: '0rem',
  width: '0%',
  height: '0vh',
  top: '-0em',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const myStyle = style({
  margin: '0',
  padding: '0',
  width: '0',
  height: '0',
  top: '0',
});

香草-摘录/优先逻辑-财产

此规则强制使用 CSS 逻辑属性而非香草-提取样式声明中的物理(向)属性. 逻辑属性适应了不同的书写方向(LTR/RTL)和书写模式,使你的作风更加国际化而友好. 支持 140+ 属性映射跨边距,贴地,边框,内置,大小,外溢,和滚动属性. 配置允许列表允许您通过 allow 选项(支持骆驼Case和kebab-case).

带有允许列表的配置 :

{
  "rules": {
    "vanilla-extract/prefer-logical-properties": ["error", { "allow": ["top", "left"] }]
  }
}
// ❌ Incorrect
import { style } from '@vanilla-extract/css';

export const box = style({
  marginLeft: '1rem',
  paddingTop: '2rem',
  width: '100%',
  borderRight: '1px solid',
  textAlign: 'left',
});

// ✅ Correct
import { style } from '@vanilla-extract/css';

export const box = style({
  marginInlineStart: '1rem',
  paddingBlockStart: '2rem',
  inlineSize: '100%',
  borderInlineEnd: '1px solid',
  textAlign: 'start',
});

香草-摘录/预选主题

执行主题符号而不是硬码的 CSS 值. 分析您的主题合同文件并给出建议 特定符号 当找到匹配时.

选项 :

选项类型默认说明
themeContractsstring[][]主题合同文件路径( 相对于项目根或绝对)
checkColorsbooleantrue检查颜色( hex, rgb, hsl, 命名)
checkSpacingbooleantrue检查间隔( 边距、 垫入、 间隙、 宽度、 高度)
checkFontSizesbooleantrue检查字体大小( fontSize, 行高)
checkBorderRadiusbooleantrue检查边框半径值
checkBorderWidthsbooleantrue检查边框宽度(包括 border 缩写)
checkShadowsbooleantrue检查阴影( 框 Shadow, 文本 Shadow, 过滤器)
checkZIndexbooleantrue检查 Z 索引值
checkOpacitybooleantrue检查不透明值
checkFontWeightsbooleantrue检查字体权重( 数字并命名)
checkTransitionsbooleantrue检查转换和动画
allowedValuesstring[][]白色列表特定值( 例如 ), ["0", "auto", "100vh"](中文(简体) )
allowedPropertiesstring[][]跳过检查特定属性
autoFixbooleanfalse当一个符号匹配时自动修正
remBasenumber16基本字体大小 rem() 计算
checkHelperFunctionsbooleanfalse检查助手的呼叫像 rem(48), (中文(简体) ), `${rem(4)}`

抚养关系说明

本规则使用安全表达式评估器可选择分析帮助者在 checkHelperFunctions 已启用。 为此,插件内部依赖 @babel/parser 财务报告和审定财务报表 @babel/types 以解析小表达式片段(例如模板字节, rem() 电话). 这些被运出为插件依赖,所以用户不需要手动安装. 它们只有在 checkHelperFunctions 打开.

示例

{
  "rules": {
    "vanilla-extract/prefer-theme-tokens": ["error", {
      "themeContracts": ["./src/theme.css.ts"],
      "checkColors": true,
      "checkSpacing": true,
      "allowedValues": ["0", "auto", "100%"],
      "allowedProperties": ["borderWidth"],
      "autoFix": false,
      "checkHelperFunctions": false
    }]
  }
}

如何运作:

  1. 分析主题合同 - 阅读主题文件并评价计算值:

    • rem(16) → "1rem"
    • `${rem(4)} ${rem(8)}` → "0.25rem 0.5rem"
    • 算术表达式
  2. 检测硬编码值 - 检查字面、数字和(可选的)帮助函数:

    color: '#0055FF'           // ❌ Always flagged
    padding: '16px'            // ❌ Always flagged
    opacity: 0.5               // ❌ Always flagged (numeric literal)
    margin: rem(48)            // ❌ Only with checkHelperFunctions: true
    boxShadow: `${rem(4)}...`  // ❌ Only with checkHelperFunctions: true
    
  3. 建议特定符号 - 将值与主题符号相匹配:

    ❌ Hard-coded color '#0055FF'. Use theme token: vars.colors.brand
    ❌ Hard-coded padding '16px'. Use theme token: vars.spacing.md
    
    • 单一匹配: 显示一个建议 + 自动修正( 如果启用)
    • 多个匹配: 全部显示为快速修复选项

主题合同实例:

// theme.css.ts
export const [themeClass, vars] = createTheme({
  colors: { brand: '#0055FF', text: '#1f2937' },
  spacing: { sm: '8px', md: '16px' },
});

// styles.css.ts
export const button = style({
  backgroundColor: '#0055FF',  // ❌ Use vars.colors.brand
  padding: '8px',              // ❌ Use vars.spacing.sm
});

帮助函数检测 :

默认情况下, 只检查 字节启用 checkHelperFunctions: true 还检查计算值:

// checkHelperFunctions: false (default)
padding: rem(48)   // ✅ Not flagged
padding: '3rem'    // ❌ Flagged

// checkHelperFunctions: true
padding: rem(48)   // ❌ Flagged if theme has matching token
padding: '3rem'    // ❌ Flagged if theme has matching token

说明: Opt-in rule (不在推荐配置中). 准备执行设计符时启用 .

字体面部声明

对于 fontFace 财务报告和审定财务报表 globalFontFace API 调用,所有三种订购规则(同心同德、同心同德)都执行 同一特殊订单:

  1. 这个 src 属性总是先出现
  2. 所有剩余属性按字母顺序排序

采用这种特殊处理方式的原因是:

  • 这个 src 属性是字体面额声明中最重要的属性
  • 一致订购提高了这些特定API的可读性
  • 字体相关属性具有专门性,并受益于标准化订购
// ✅ Correct ordering for font faces
export const theFont = fontFace({
  src: ['url("/fonts/MyFont.woff2") format("woff2")', 'url("/fonts/MyFont.woff") format("woff")'],
  ascentOverride: '90%',
  descentOverride: '10%',
  fontDisplay: 'swap',
  fontFeatureSettings: '"liga" 1',
  fontStretch: 'normal',
  // ...other properties in alphabetical order
});

有观点,但这是它是什么。 如果有人有更好的订单建议 告诉我!

同心CSS模型

以下是所有可用的团体列表 来自提供 同心团 数组 :

  1. 框大小
  2. 职位
  3. 显示
  4. 弹性
  5. 网格
  6. 对齐
  7. 栏
  8. 转换
  9. 过渡
  10. 可见度
  11. 形状
  12. 边距
  13. 大纲
  14. 边框
  15. 框阴影
  16. 背景情况
  17. 光标
  18. 粘贴
  19. 维度
  20. 溢出额
  21. 列表样式
  22. 图表
  23. 动画
  24. 文本
  25. 文本间距
  26. 字体
  27. 内容
  28. 计数器
  29. 间断

这些组别代表了CSS属性的不同类别,由外到内按同心排列. 每个组包含相关的CSS属性,会影响元素的造型和布局的特定方面.

路线图

路线图概述了该项目的现状和未来计划:

已完成的里程碑

  • 初始发布时支持字母,同心,以及自定义组 CSS 命令.
  • 将自动固定能力整合入ESLint.
  • 支持多个香草-提取API(例如, style, (中文(简体) ), styleVariants, (中文(简体) ), recipe, (中文(简体) ), globalStyle, (中文(简体) ), fontFace(见a/c.5/49/70,附件).
  • no-empty-style-blocks 规则不允许空块.
  • 为插件推荐的 ESLint 配置 .
  • no-zero-unit 规则,当值为零时,取消单位.
  • no-unknown-unit 规则不允许未知单位.
  • no-trailing-zero 规则不允许在数字后出现零.
  • 支持通过扩展字段使用插件推荐的配置( 如在 问题3(中文(简体) )
  • 全面规则测试.
  • no-px-unit 不允许使用 px 带有可配置的白名单的单位.
  • prefer-logical-properties 规则强制使用逻辑属性.
  • prefer-theme-tokens 规则执行主题符号而不是硬编码值,用于颜色、间隔、字体大小、边框半径、边框宽度、阴影、z-index、不透明、字体权重和过渡/动画(可选择评价帮助器函数和模板文字).
  • no-unitless-values 规则不允许需要单位的 CSS 属性的无单位数值.

即将到来的特点

  • property-unit-match 规则执行 CSS 属性规格的有效单位. 说明: 此特性将仅是 如果社区有足够的兴趣就执行.
  • 选择在用户定义的同心组合内按字母顺序排序属性,而不是遵循同心组合 秩序。 秩序. 说明:这个特性只有在社区有足够的兴趣的情况下才会被实施.

捐款

当然,欢迎所有善意的贡献! 请随意提交拉动请求或通过 GitHub问题.

许可证

这个项目根据麻省理工学院许可证颁发——见 自由主义 详细文件.

版本与发布记录

@antebudimir/eslint-plugin-vanilla-extract 共发布 29 个版本,首次发布于 2025/03/05;过去 12 个月发布了 9 个版本。

版本发布日期距今
2.0.0latest2026/11/016 天前
1.18.12026/10/1721 天前
1.18.02026/10/1226 天前
1.17.12026/10/1226 天前
1.17.02026/05/315 个月前
1.16.02025/12/0211 个月前

关于 @antebudimir/eslint-plugin-vanilla-extract 的常见问题

@antebudimir/eslint-plugin-vanilla-extract 是什么?

综合ESLint插件,用于有 CSS 财产订单的香草-提取,样式验证,以及最佳做法执行. 支持字母顺序,同心和自定义的 CSS 命令,自动固定,以及零运行时的安全性.

如何安装 @antebudimir/eslint-plugin-vanilla-extract?

在项目目录运行 npm install @antebudimir/eslint-plugin-vanilla-extract,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:eslint(>=8.57.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@antebudimir/eslint-plugin-vanilla-extract 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@antebudimir/eslint-plugin-vanilla-extract 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@antebudimir/eslint-plugin-vanilla-extract 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@antebudimir/eslint-plugin-vanilla-extract 可以商用吗?

@antebudimir/eslint-plugin-vanilla-extract 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@antebudimir/eslint-plugin-vanilla-extract 的下载量有多少?

根据 npm 官方下载统计,@antebudimir/eslint-plugin-vanilla-extract 在 2026/10/06 – 2026/11/04 这 30 天内被下载 48,467 次,日均约 1,616 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@antebudimir/eslint-plugin-vanilla-extract 还在维护吗?

最新版本 2.0.0 发布于 2026/11/01(6 天前);至今共发布 29 个版本,其中过去 12 个月发布了 9 个;首次发布于 2025/03/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。