前端工程化工具系列(三) —— Stylelint(v16.6.1):CSS/SCSS 代码质量工具

发布于:2024-06-02 ⋅ 阅读:(68) ⋅ 点赞:(0)

Stylelint 是 CSS/SCSS 代码的静态分析工具,用于检查代码中的错误和样式违规。

1. 环境要求

v16 以上的 Stylelint,支持 Node.js 的版本为 v18.12.0+。
在命令行中输入以下内容来查看当前系统中 node 的版本。

node -v

Node.js 推荐使用 v18.20.3 或者 v20.13.1。
这里使用的包管理器是 PNPM,版本为 v9.1.4。

2 安装

2.1 针对 CSS

pnpm install -D stylelint stylelint-config-standard stylelint-order

2.2 针对 SCSS(包含CSS)

pnpm install -D stylelint stylelint-order stylelint-config-standard stylelint-config-standard-scss stylelint-config-sass-guidelines stylelint-scss

3 配置

在项目根目录下创建 stylelint.config.js 文件,填入以下内容:

3.1 针对 CSS

export default {
  // 继承已有配置 如果规则与自己想要的冲突 可以在下面rules中修改规则
  extends: ['stylelint-config-standard'],
  // 插件是由社区创建的规则或规则集 按照规则对CSS属性进行排序
  plugins: [
    // 指定排序,比如声明的块内(插件包)属性的顺序
    'stylelint-order',
  ],
  rules: {
    // 允许的最大嵌套深度为 3
    'max-nesting-depth': 3,
    // 屏蔽一些scss等语法检查
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'extend',
          'at-root',
          'debug',
          'warn',
          'error',
          'if',
          'else',
          'for',
          'each',
          'while',
          'mixin',
          'include',
          'content',
          'return',
          'function',
        ],
      },
    ],
    // 屏蔽没有申明通用字体
    'font-family-no-missing-generic-family-keyword': null,
    // ID选择器 最多使用一个
    'selector-max-id': 1,
    // 不允许使用的选择器的类型
    'selector-no-qualifying-type': null,
    // 屏蔽类选择器的检查,以确保使用字符 __
    'selector-class-pattern': null,
    // 允许的最大复合选择器为 5
    'selector-max-compound-selectors': 5,
    // 属性排序规则
    'order/properties-order': [
      [
        'content',
        'position',
        'top',
        'right',
        'bottom',
        'left',
        'z-index',
        'display',
        'vertical-align',
        'flex',
        'flex-grow',
        'flex-shrink',
        'flex-basis',
        'flex-direction',
        'flex-flow',
        'flex-wrap',
        'grid',
        'grid-area',
        'grid-template',
        'grid-template-areas',
        'grid-template-rows',
        'grid-template-columns',
        'grid-row',
        'grid-row-start',
        'grid-row-end',
        'grid-column',
        'grid-column-start',
        'grid-column-end',
        'grid-auto-rows',
        'grid-auto-columns',
        'grid-auto-flow',
        'grid-gap',
        'grid-row-gap',
        'grid-column-gap',
        'gap',
        'row-gap',
        'column-gap',
        'align-content',
        'align-items',
        'align-self',
        'justify-content',
        'justify-items',
        'justify-self',
        'order',
        'float',
        'clear',
        'object-fit',
        'overflow',
        'overflow-x',
        'overflow-y',
        'overflow-scrolling',
        'clip',
        //
        'box-sizing',
        'width',
        'min-width',
        'max-width',
        'height',
        'min-height',
        'max-height',
        'margin',
        'margin-top',
        'margin-right',
        'margin-bottom',
        'margin-left',
        'padding',
        'padding-top',
        'padding-right',
        'padding-bottom',
        'padding-left',
        'border',
        'border-spacing',
        'border-collapse',
        'border-width',
        'border-style',
        'border-color',
        'border-top',
        'border-top-width',
        'border-top-style',
        'border-top-color',
        'border-right',
        'border-right-width',
        'border-right-style',
        'border-right-color',
        'border-bottom',
        'border-bottom-width',
        'border-bottom-style',
        'border-bottom-color',
        'border-left',
        'border-left-width',
        'border-left-style',
        'border-left-color',
        'border-radius',
        'border-top-left-radius',
        'border-top-right-radius',
        'border-bottom-right-radius',
        'border-bottom-left-radius',
        'border-image',
        'border-image-source',
        'border-image-slice',
        'border-image-width',
        'border-image-outset',
        'border-image-repeat',
        'border-top-image',
        'border-right-image',
        'border-bottom-image',
        'border-left-image',
        'border-corner-image',
        'border-top-left-image',
        'border-top-right-image',
        'border-bottom-right-image',
        'border-bottom-left-image',
        //
        'background',
        'background-color',
        'background-image',
        'background-attachment',
        'background-position',
        'background-position-x',
        'background-position-y',
        'background-clip',
        'background-origin',
        'background-size',
        'background-repeat',
        'color',
        'box-decoration-break',
        'box-shadow',
        'outline',
        'outline-width',
        'outline-style',
        'outline-color',
        'outline-offset',
        'table-layout',
        'caption-side',
        'empty-cells',
        'list-style',
        'list-style-position',
        'list-style-type',
        'list-style-image',
        //
        'font',
        'font-weight',
        'font-style',
        'font-variant',
        'font-size-adjust',
        'font-stretch',
        'font-size',
        'font-family',
        'src',
        'line-height',
        'letter-spacing',
        'quotes',
        'counter-increment',
        'counter-reset',
        '-ms-writing-mode',
        'text-align',
        'text-align-last',
        'text-decoration',
        'text-emphasis',
        'text-emphasis-position',
        'text-emphasis-style',
        'text-emphasis-color',
        'text-indent',
        'text-justify',
        'text-outline',
        'text-transform',
        'text-wrap',
        'text-overflow',
        'text-overflow-ellipsis',
        'text-overflow-mode',
        'text-shadow',
        'white-space',
        'word-spacing',
        'word-wrap',
        'word-break',
        'overflow-wrap',
        'tab-size',
        'hyphens',
        'interpolation-mode',
        //
        'opacity',
        'visibility',
        'filter',
        'resize',
        'cursor',
        'pointer-events',
        'user-select',
        //
        'unicode-bidi',
        'direction',
        'columns',
        'column-span',
        'column-width',
        'column-count',
        'column-fill',
        'column-gap',
        'column-rule',
        'column-rule-width',
        'column-rule-style',
        'column-rule-color',
        'break-before',
        'break-inside',
        'break-after',
        'page-break-before',
        'page-break-inside',
        'page-break-after',
        'orphans',
        'widows',
        'zoom',
        'max-zoom',
        'min-zoom',
        'user-zoom',
        'orientation',
        'fill',
        'stroke',
        //
        'transition',
        'transition-delay',
        'transition-timing-function',
        'transition-duration',
        'transition-property',
        'transform',
        'transform-origin',
        'animation',
        'animation-name',
        'animation-duration',
        'animation-play-state',
        'animation-timing-function',
        'animation-delay',
        'animation-iteration-count',
        'animation-direction',
        'animation-fill-mode',
      ],
      {
        unspecified: 'bottom',
        severity: 'warning',
      },
    ],
    // 屏蔽属性按字母顺序检查
    'order/properties-alphabetical-order': null,
  },
};

3.2 针对 SCSS

export default {
  // 继承已有配置 如果规则与自己想要的冲突 可以在下面rules中修改规则
  extends: [
    'stylelint-config-standard',
    'stylelint-config-standard-scss',
    'stylelint-config-sass-guidelines',
  ],
  // 插件是由社区创建的规则或规则集 按照规则对CSS属性进行排序
  plugins: [
    // 执行各种各样的 SCSS语法特性检测规则(插件包)
    'stylelint-scss',
    // 指定排序,比如声明的块内(插件包)属性的顺序
    'stylelint-order',
  ],
  rules: {
    // 允许的最大嵌套深度为 3
    'max-nesting-depth': 3,
    // 屏蔽一些scss等语法检查
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'extend',
          'at-root',
          'debug',
          'warn',
          'error',
          'if',
          'else',
          'for',
          'each',
          'while',
          'mixin',
          'include',
          'content',
          'return',
          'function',
        ],
      },
    ],
    // 屏蔽没有申明通用字体
    'font-family-no-missing-generic-family-keyword': null,
    // ID选择器 最多使用一个
    'selector-max-id': 1,
    // 不允许使用的选择器的类型
    'selector-no-qualifying-type': null,
    // 屏蔽类选择器的检查,以确保使用字符 __
    'selector-class-pattern': null,
    // 允许的最大复合选择器为 5
    'selector-max-compound-selectors': 5,
    // 属性排序规则
    'order/properties-order': [
      [
        'content',
        'position',
        'top',
        'right',
        'bottom',
        'left',
        'z-index',
        'display',
        'vertical-align',
        'flex',
        'flex-grow',
        'flex-shrink',
        'flex-basis',
        'flex-direction',
        'flex-flow',
        'flex-wrap',
        'grid',
        'grid-area',
        'grid-template',
        'grid-template-areas',
        'grid-template-rows',
        'grid-template-columns',
        'grid-row',
        'grid-row-start',
        'grid-row-end',
        'grid-column',
        'grid-column-start',
        'grid-column-end',
        'grid-auto-rows',
        'grid-auto-columns',
        'grid-auto-flow',
        'grid-gap',
        'grid-row-gap',
        'grid-column-gap',
        'gap',
        'row-gap',
        'column-gap',
        'align-content',
        'align-items',
        'align-self',
        'justify-content',
        'justify-items',
        'justify-self',
        'order',
        'float',
        'clear',
        'object-fit',
        'overflow',
        'overflow-x',
        'overflow-y',
        'overflow-scrolling',
        'clip',
        //
        'box-sizing',
        'width',
        'min-width',
        'max-width',
        'height',
        'min-height',
        'max-height',
        'margin',
        'margin-top',
        'margin-right',
        'margin-bottom',
        'margin-left',
        'padding',
        'padding-top',
        'padding-right',
        'padding-bottom',
        'padding-left',
        'border',
        'border-spacing',
        'border-collapse',
        'border-width',
        'border-style',
        'border-color',
        'border-top',
        'border-top-width',
        'border-top-style',
        'border-top-color',
        'border-right',
        'border-right-width',
        'border-right-style',
        'border-right-color',
        'border-bottom',
        'border-bottom-width',
        'border-bottom-style',
        'border-bottom-color',
        'border-left',
        'border-left-width',
        'border-left-style',
        'border-left-color',
        'border-radius',
        'border-top-left-radius',
        'border-top-right-radius',
        'border-bottom-right-radius',
        'border-bottom-left-radius',
        'border-image',
        'border-image-source',
        'border-image-slice',
        'border-image-width',
        'border-image-outset',
        'border-image-repeat',
        'border-top-image',
        'border-right-image',
        'border-bottom-image',
        'border-left-image',
        'border-corner-image',
        'border-top-left-image',
        'border-top-right-image',
        'border-bottom-right-image',
        'border-bottom-left-image',
        //
        'background',
        'background-color',
        'background-image',
        'background-attachment',
        'background-position',
        'background-position-x',
        'background-position-y',
        'background-clip',
        'background-origin',
        'background-size',
        'background-repeat',
        'color',
        'box-decoration-break',
        'box-shadow',
        'outline',
        'outline-width',
        'outline-style',
        'outline-color',
        'outline-offset',
        'table-layout',
        'caption-side',
        'empty-cells',
        'list-style',
        'list-style-position',
        'list-style-type',
        'list-style-image',
        //
        'font',
        'font-weight',
        'font-style',
        'font-variant',
        'font-size-adjust',
        'font-stretch',
        'font-size',
        'font-family',
        'src',
        'line-height',
        'letter-spacing',
        'quotes',
        'counter-increment',
        'counter-reset',
        '-ms-writing-mode',
        'text-align',
        'text-align-last',
        'text-decoration',
        'text-emphasis',
        'text-emphasis-position',
        'text-emphasis-style',
        'text-emphasis-color',
        'text-indent',
        'text-justify',
        'text-outline',
        'text-transform',
        'text-wrap',
        'text-overflow',
        'text-overflow-ellipsis',
        'text-overflow-mode',
        'text-shadow',
        'white-space',
        'word-spacing',
        'word-wrap',
        'word-break',
        'overflow-wrap',
        'tab-size',
        'hyphens',
        'interpolation-mode',
        //
        'opacity',
        'visibility',
        'filter',
        'resize',
        'cursor',
        'pointer-events',
        'user-select',
        //
        'unicode-bidi',
        'direction',
        'columns',
        'column-span',
        'column-width',
        'column-count',
        'column-fill',
        'column-gap',
        'column-rule',
        'column-rule-width',
        'column-rule-style',
        'column-rule-color',
        'break-before',
        'break-inside',
        'break-after',
        'page-break-before',
        'page-break-inside',
        'page-break-after',
        'orphans',
        'widows',
        'zoom',
        'max-zoom',
        'min-zoom',
        'user-zoom',
        'orientation',
        'fill',
        'stroke',
        //
        'transition',
        'transition-delay',
        'transition-timing-function',
        'transition-duration',
        'transition-property',
        'transform',
        'transform-origin',
        'animation',
        'animation-name',
        'animation-duration',
        'animation-play-state',
        'animation-timing-function',
        'animation-delay',
        'animation-iteration-count',
        'animation-direction',
        'animation-fill-mode',
      ],
      {
        unspecified: 'bottom',
        severity: 'warning',
      },
    ],
    // 屏蔽属性按字母顺序检查
    'order/properties-alphabetical-order': null,
  },
};

4 结合 Husky

利用 Husky 在 Git Commit 时自动校验文件中的样式内容,如不符合规范,则不能被 Commit。详细操作见前端工程化工具系列(五)中的 2.1节。