原文地址: https://www.smashingmagazine.com/2016/05/stylelint-the-style-sheet-linter-weve-always-wanted/
每个人都想要有一个干净、始终如一的代码库,无论使用的是什么开发语言。很多开发者习惯于在例如 JavaScript 和 Python 的程序语言中设置 linter , 但很少在样式表中用到它。在这片文章中,我们会介绍 stylelint —— 一个用于样式表的 linter。
我们很快就会了解为什么在样式表中使用 lint 很重要,stylelint 如何向样式表发出指令以及我们如何能够避免错误的发生。最后,我们会了解如何使用 stylelint 以及尽快开始使用它。
linter 是一个当一段代码不能满足规定的 linter 的配置规则时用于分析代码并报错的工具。
我们很多人在开源的代码库环境中工作。如果没有一套严格的代码样式规则,代码很快就会变得一塌糊涂。说不定你的代码已经是一团糟了,你很想清理下,并且让代码定时自动清理。及时你的工作只涉及到样式表,你也同样希望这些代码可以前后一致。
当然,你的团队可能有写在维基或者其他什么地方的规定代码样式的纯文本。但总有一些人为因素无法实现原本的目的:人会犯错误——虽然从来都不是故意的。
而且,即便你完全按照代码样式的要求来做,你开源项目的同事或参与者却不一定会。如果没有 linter,你需要自己检查样式的代码和错误。没有人活该在本可自动完成的事情上花费时间。linter 可以显著减少预览代码的时间,因为你根本不需要花费时间检查样式以及为每一处错误做标注。你可以随意检查代码的功能,而不是它的样子。
Stylelint 是一款由 David Clark, Richard Hallows, Evilebot Tnawi 和 社区 使用 JavaScript 语言写的非常实用的、时髦的样式表 linter。它的规则速度、兼容性和代码质量,而且完全不能主观改变。Sylelint 有一百多条规则,而且这个数字还在不断增长。不过不用害怕,在默认情况下所有规则都是禁用的,只会让你使用你想用的。Stylelint 不仅可以侦测 CSS,还可以侦测 Sass, SugarSS 以及其他 PostCSS 可以解析的语法(因为 Stylelint 是在其基础上编写的)。
Stylelint 对于样式表的作用,就相当于 ESLint 对于 JavaScript 的作用。
Stylelin 有一百多条规则,可以划分为三组:样式规则,代码可维护性规则,以及检查使得代码在浏览器中用途改变的错误的规则。样式规格检查分隔(比如冒号)、换行符、缩进等等。代码可维护性规则可能在 ID 在选择器中被使用或者关键词 !important 用在声明中时会报错。检查错误规则可能会报告不正确的十六进制颜色或者一个覆盖了别的声明的缩写。
我不会在这里详细介绍样式规则(它们实在是太多了)。不过,我会介绍一些帮助维护并且防止出错的规则。
用于防止缩写覆盖其他声明的规则(又或者说,在 stylelint 语法中叫 declaration-block-no-shorthand-property-overrides )会防止例如以下这种情况的发生:
div { padding-left: 20px; /* 该属性被覆盖了 */ padding: 10px;}
Stylelin 同样会防止使用不合法的十六进制颜色( color-no-invalid-hex ):
p { color: #44;}
它同样禁止重复的属性( declaration-block-no-duplicate-properties ):
p { color: #000; /* 该属性是重复的 */ margin: 0 0 1.25em; color: #777;}
你可能会使用老语法来实现倾斜效果。Stylelint 会这样来检查( function-linear-gradient-no-nonstandard-direction ):
/* 不正确的属性 */.block { background: linear-gradient(bottom, #fff, #000);} /* 正确的属性 */.block { background: linear-gradient(to bottom, #fff, #000);
当你需要用另一规则来覆盖当前属性时,在该属性使用关键字 !important 会造成*烦。避免 !important 和 declaration-no-important 规则一起使用。
在选择器( #main )中使用 ID 以及使用类型选择器(也就是一个基于 HTML 元素的选择器——比如 .block p )可能会在你的开发方法学(比如, BEM )中被禁用。在这种情况下, selector-no-id 和 selector-no-type 可以派上用场。
有时候你会拼错或者忘记把什么加到样式表。比如在动画场景中, no-unknown-animations 在动画对象名称不符合 @keyframes 规则时会报错。
当我们有了 Autoprefixer 的时候你干嘛还让值、属性名和选择器的前缀来烦你?让 Autoprefixer 来解决这些,使用 value-no-vendor-prefix , property-no-vendor-prefix 和 selector-no-vendor-prefix 规则来防止前缀被添加。
当然,Stylelint 还有更多的规则。
除了默认规则,stylelint 也支持插件,所以你还可以扩展使用新的规则。现在还没有太多可使用的插件,不过现有的这几个非常方便。
有时候,开发者会过度嵌套。因为所有的预处理器都支持嵌套,而嵌套太深导致的结果是增加选择器特异性而且会引起这些规则的维护问题。这里有一个典型的例子:
.header { .nav { .item { .link { color: blue; &:hover { color: red; } } } }}
呈现结果如下:
.header .nav .item .link { color: blue;}.header .nav .item .link:hover { color: red;}
Stylelint 针对这一问题并没有立即可用的规则,但有一个可以为嵌套深度添加规则的插件( stylelint-statement-max-nesting-depth ).
使用任何插件之前需要安装:
npminstallstylelint-statement-max-nesting-depth --save-dev
然后,在 plugins 数列中添加插件到配置文件里。添加新的规则并进行配置:
{ "plugins": [ "stylelint-statement-max-nesting-depth" ], "rules": { "statement-max-nesting-depth": 2 }}
在以上的配置文件中,我们把嵌套深度设定成最大为 2。所以,我们会被提示将我们的早期示例简化成一个低嵌套的示例(在这个例子中,两级):
.nav { .link { color: blue; &:hover { color: red; } }}
或者我们可以进一步简化至一级嵌套:
.nav-link { color: blue; &:hover { color: red; }}
我们在此不会对插件进行一一详述,但还是要推荐一二:
如果你想要一个新的规则, 你可以写自己的插件 。
配置是使用 linter 过程中最困难的部分,而且也是最耗时的。但我们这里有捷径和不同的策略使stylelint 更加容易配置。
你的配置文件会变的越来越大,所以存储 stylelint 的配置文件最简单的方法是把它存储在一个单独的 JSON 文件中,命令为 .stylelintrc 。通过这种方式,这个文件可以在命令行界面使用,或者在一个构建工具或者代码编辑器中使用。
一个非常简单的配置文件可能是下面的样子:
{ "rules": { "color-hex-case": "lower", "color-hex-length": "short", "color-no-invalid-hex": true }}
有三种配置策略。首先,一种简单的方式,是扩展别人的配置文件(stylelint 可以支持的),然后添加、去除或者优化你想要改变的规则。开发者已经使配置文件基本符合大多数人的需求。你可以使用 npm 包来安装一个:
npminstallstylelint-congif-standard --save-dev
然后,在你自己的配置文件中,你可以根据需要扩展或者覆盖他们的规则:
{ "extends": "stylelint-config-standard", "rules": { "indentation": "tab", "number-leading-zero": null }}
在这个例子中,我们已经扩展了 stylelint-config-standard ,并且改变了 indentation 的规则使它的功能变为“制表符”,并且去除了 number-leading-zero 规则。
第二种策略是以空白文件开始,然后添加你需要的规则缓慢进行配置。比如,你目前也许根本不关心编码样式而只想专注于规避错误:
{ "rules": { "color-no-invalid-hex": true, "declaration-block-no-duplicate-properties": true, "declaration-block-no-shorthand-property-overrides": true, "function-linear-gradient-no-nonstandard-direction": true }}
以后,你还可以添加更多的规则。
第三种策略是检查所有的策略并且一个一个添加。我更喜欢这种方式因为我想尽可能多的检查并且使用 stylelint 的全部功能。当然,这也是最耗时的策略,但它的效果是最好的。为了更容易操作,stylelint 开发者创建了一个包含所有规则的 空白样板文件 。
每一个启用的规则都有一个错误严重程度。这意味着任何不满足此项的规则都无法通过测试。对任何规则,严重级别都可被降低至警告,这将防止无法通过测试。如果你设定了一个规则并且不想构筑失效,这就会很有用,比如团队适应新的规则的时候。
{ "rules": { "color-hex-case": ["lower", { "severity": "warning" }] }}
在这个例子里,如果十六进制颜色写错了,stylelint 会警告,不过不会报错。
有时候我们需要把一些东西添加进样式表,但 stylelint 配置文件不允许。比如,我们不被允许使用关键字 important ,但我们也许需要在一个地方用它来重置一些第三方小插件。我们不想因为这一个特殊情况就把这个规则作废。但我们也不想每次都看到这个错误。辛运的是,我们可以在一行 CSS 中添加注释来禁用某一规则:
.widget { display: none !important; /* stylelint-disable-line declaration-no-important */}
或者我们可以在一块 CSS 中禁用 stylelint。
/* stylelint-disable */.third-party-code {}/* stylelint-enable */
Stylelint 可以通过很多方式使用:在命令行中、在构建工具中(比如 Gulp, Grunt 或 Webpack),在代码编辑器中或者 Git 库中的 Git 提交分级变化。我在这里主要讲两种方式:
当你想要 lint 一个没有 stylelint 的项目或者在 npm 脚本使用 stylelint 时,使用命名行非常方便。
安装全局 stylelint:
npminstallstylelint -g
之后,在你的终端任意位置都可使用:
stylelint "styles/**/*.css"
这个命令会初始化 style 目录以及任意子目录里的所有 CSS 文件。
为了初始化 SCSS 或者 SugarSS 文件,添加 syntax 选项:
stylelint "styles/*.scss" --syntaxscss
这个配置可以被明确指定:
stylelint "styles/*.css" --configbar/myStylelintConfig.json
如果没有明确指定,stlelint 会在当前工作目录查找一个 .stylelintrc 文件。
结合 GULP 使用 stylelint ,可把它当做 PostCSS 插件使用。你需要安装以下包:
npminstallgulp-postcssstylelintpostcss-reporter --save-dev
gulp-postcess 是所有 PostCSS 的分流道, postcss-reporter 从 stylelint 输出较好的错误和警告。
var postcss = require('gulp-postcss');var reporter = require('postcss-reporter');var stylelint = require('stylelint'); gulp.task('lint:css', function() { return gulp.src('src/**/*.css') .pipe(postcss([ stylelint({ /* options */ }), reporter({ clearMessages: true }) ]));});
输出结果就像这样:
初始化除 CSS 以外的样式表,你需要安装适当的语法。比方说,初始化 SCSS,我们需要安装 postcss-scss :
npminstallpostcss-scss --savedev
然后,配置 gulp-postcss 来使用这个语法:
var postcss = require('gulp-postcss');var reporter = require('postcss-reporter');var stylelint = require('stylelint');var scss = require("postcss-scss"); gulp.task('lint:css', function() { return gulp.src('src/**/*.scss') .pipe(postcss( [ stylelint({ /* options */ }), reporter({ clearMessages: true }) ], { syntax: scss } ));});
你可以明确指定配置文件,不然,stylelint 会查找 .stylelintrc 文件。
Stylelint 是一款出色的样式表 linter。它带来清晰的代码并且防止你出错。它对每一个人都很实用:个人开发者、团队和开源维护者。一旦你开始使用,你将不会再听到诸如“你忘记在这里加空格”或者“你忘记移除这里”之类的评论。快乐开发,希望你有个舒适的代码预览。