HowToFix
常见错误修复
JavaScript
JS RULE000 syntax error。
语法错误的原因很多,这里只说最常见的作为 FIS
的 widget 的写法导致的语法错误。
var mod = function () {
// 这里是模块主要代码
}
return mod;
语法错误的原因是在 function
之外使用 return
语句,这是 FIS 1.x
的写法, FIS 2.x
之后的写法见下面的修正代码。
FIS 1.x
的 widget 这里之所以可以这样写,是因为 FIS
在构建后会自动 wrap
一个 function
。
同时兼容 FIS
,又不会产生语法错误的写法是:
// 主要代码同上
// return mod; 这里可以改成如下:
// exports = mod;
// 不过更推荐这种兼容 `commonjs` 的写法:
module.exports = mod;
JS RULE003 [强制] 使用 4
个空格做为一个缩进层级,不允许使用 2
个空格 或 tab
字符。
这个问题通常发生在使用 tab
作为缩进,还有部分是由于前面出现的代码中有不恰当的换行或缩进影响的,具体需要使用 fecs
直接检查查看详细的错误信息。
比较容易发现的,是数组内的元素或函数的参数间换行,当内部需要换行时(比如超过 120 字符或排版美观需要),括号内侧也必须换行--左括号之后换行,右括号之前换行。第一个换行的缩进,需要比左括号所在行多一个缩进,右括号所在行的缩进则与左括号所在行的保持一致。
一个特殊的 case 是使用数组作 HTML 字符拼接时,除满足上面所述的缩进外,其它元素间的最多可以差一个缩进(在兄弟节点时可以相等,子节点时增加一个,父节点结束标记减少一个)。如果数组未被识别为 HTML 字符拼接,可以通过增加注释来标识:
// html
var html = [
objectType,
functionExpressionType,
...
];
JS RULE007 [强制] if / else / for / while / function / switch / do / try / catch / finally
关键字后,必须有一个空格。
文字描述已经很清楚,但很多 RD 同学碰到时可能不明白怎么修改,其实只需在以上关键字后加一个空格即可。
JS RULE008 [强制] 在对象创建时,属性中的 :
之后必须有空格,:
之前不允许有空格。
对象创建是指直接使用 {
和 }
创建的对象直接量,一般情况下,在 :
前是不允许有空格而在它之后是必须有空格的。特殊情况是当使用 :
作对象字段的对齐排版时,允许 :
前有空格。如果提示某些属性名后、:
前缺少空格,是由于当前对象的属性大部分相对于 :
对齐了。
JS RULE015 [强制] 每行不得超过 120
个字符。
除了很长的正则和 URL,这个只能通过添加适当的换行和缩进排版来修复。
- 对于参数超长的,必须在
(
后和)
前换行,)
的缩进跟(
所在行对齐:
// bad
var longFunctionNameHereForTest = function (firstParamForTest, secondParamForTest, thirdParamForTest, fourthParamForTest, fifthParamForTest, sixthParamForTest) {
};
// bad
var longFunctionNameHereForTest = function (
firstParamForTest, secondParamForTest, thirdParamForTest, fourthParamForTest, fifthParamForTest, sixthParamForTest) {
};
// good
var longFunctionNameHereForTest = function (
firstParamForTest, secondParamForTest, thirdParamForTest,
fourthParamForTest, fifthParamForTest, sixthParamForTest
) {
};
// good
var longFunctionNameHereForTest = function (
firstParamForTest,
secondParamForTest,
thirdParamForTest,
fourthParamForTest,
fifthParamForTest,
sixthParamForTest,
seventhParamForTest
) {
};
数组项导致的超长也是同样的处理方式。
对于 HTML 字符拼接导致超长的,可参考 HTML 标签嵌套方式对齐:
// bad
var html = '<div class="class-for-block"><ul class="class-for-ul"><li><a href="http://www.domain.com/path/to/page/one/"></a></li><li><a href="http://www.domain.com/path/to/page/two/"></a></li></ul></div>';
// bad (jsx)
var html = <div className="class-for-block"><ul className="class-for-ul"><li><a href="http://www.domain.com/path/to/page/one/"></a></li><li><a href="http://www.domain.com/path/to/page/two/"></a></li></ul></div>;
// good
var html = ''
+ '<div class="class-for-block">'
+ '<ul class="class-for-ul">'
+ '<li><a href="http://www.domain.com/path/to/page/one/"></a></li>'
+ '<li><a href="http://www.domain.com/path/to/page/two/"></a></li>'
+ '</ul>'
+ '</div>';
// good
var html = ''
+ '<div class="class-for-block">'
+ '<ul class="class-for-ul">'
+ '<li>'
+ '<a href="http://www.domain.com/path/to/page/one/"></a>'
+ '</li>'
+ '<li>'
+ '<a href="http://www.domain.com/path/to/page/two/"></a>'
+ '</li>'
+ '</ul>'
+ '</div>';
// good (jsx)
var html = (
<div className="class-for-block">
<ul className="class-for-ul">
<li><a href="http://www.domain.com/path/to/page/one/"></a></li>
<li><a href="http://www.domain.com/path/to/page/two/"></a></li>
</ul>
</div>
);
// good (jsx)
var html = (
<div className="class-for-block">
<ul className="class-for-ul">
<li>
<a href="http://www.domain.com/path/to/page/one/"></a>
</li>
<li>
<a href="http://www.domain.com/path/to/page/two/"></a>
</li>
</ul>
</div>
);
- 对于超长的正则和 URL 导致的问题,可以通过注释来屏蔽:
/* eslint-disable max-len */
// 这里是超长的正则或 URL
/* eslint-enable max-len */
JS RULE016 [强制] 运算符处换行时,运算符必须在新行的行首。
例如:
if (thisIsALongExpressionForCodeDemoView &&
thisAnotherLogExpression
)
需要改为
if (thisIsALongExpressionForCodeDemoView
&& thisAnotherLogExpression
)
JS RULE024 [强制] IIFE
必须在函数表达式外添加 (
,非 IIFE
不得在函数表达式外添加 (
。
IIFE
是指马上执行的函数表达式:
var task = function () {
// Code
return result;
}();
var func = (function () {
});
+function () {
// blablabla
}();
必须改成:
// good
var task = (function () {
// Code
return result;
})();
var func = function () {
};
(function () {
// blablabla
})();
JS RULE025 [强制] 变量
使用 Camel命名法
。
使用其他语言的同学,可能习惯使用下划线作为命名中单词的分隔符:
var foo_bar = true;
这里需要改成:
var fooBar = true;
JS RULE029 [强制] 类
使用 Pascal命名法
。
换言之,使用类的构建函数名,必须是大写字母开头。当调用了大写字母开头的函数或方法,但没有使用 new
操作符时,也是不允许的,即便结果正确。 如果是因为使用了第三方的代码,如果加 new
不影响结果的正确性,可以参见 https://www.xnip.cn/shouce/1124/72640.html 中的 《如何修复使用 jQuery
的 DataTable
插件的问题?》,否则需要使用以下方式屏蔽该条规则:
/* eslint-disable new-cap */
JS RULE030 [强制] 类的 方法 / 属性
使用 Camel命名法
。
部分情况同 《JS RULE029 [强制]
类
使用Pascal命名法
》。如果方法属性命名是受 RD 接口影响,需要使用以下方式处理:
/* eslint-disable fecs-camelcase */
// 这里是你的代码
/* eslint-enable fecs-camelcase */
- 如果有固定的模式,比如都以
api_
开头,可以这样配置:
/* eslint fecs-camelcase: [2, {ignore: ["/^api_/"]}] */
ajax.send({
api_site: 'baidu',
api_key: 'djk13-liwfu-bstdj'
});
其中 ignore 的取值是字符串数组,字符串以 /
开始和结束时,将按正则字符匹配处理。
- 如果习惯使用
_
前缀标识私有属性或方法,则需要增加@private
来避免检查:
/**
* 类描述
*
* @class
* @extends Developer
*/
var Fronteer = function () {
Developer.call(this);
/**
* 属性描述
*
* @type {string}
* @private
*/
this._level = 'T12';
// constructor body
};
util.inherits(Fronteer, Developer);
/**
* 方法描述
*
* @private
* @return {string} 返回值描述
*/
Fronteer.prototype._getLevel = function () {
};
JS RULE031 [强制] 枚举变量
使用 Pascal命名法
,枚举的属性
使用 全部字母大写,单词间下划线分隔
的命名方式。
当变量名符合 Pascal 命名法,并且值类型为对象字面量时,会要求对象的所有属性名全部字母大写,即使用常量的命名方式。
所以修改方式有两种,一是按规范要求把属性名按常量的命名方式修改(全部字母大写,单词间下划线分隔
),二是调整变量名,比如首字母恢复小写。
JS RULE044 [强制] 对于基本类型 {string}, {number}, {boolean},首字母必须小写。
意思是除了 String/Number/Boolean 类型的首字母小写,其它类型都大写,如:{Array},{Date},{Function},{Object},{RegExp}。
JS RULE045 [强制] 文件顶部必须包含文件注释,用 @file
标识文件说明。
在文件开始,必须使用 @file
对当前文件作注释(注意文档注释开始行是两个星号 /**
):
/**
* @file 介绍当前文件的说明
* @author name<email>
*/
JS RULE052 [强制] 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。
这种情况通常是漏了某些参数或返回值的注释,可以通过本地运行 fecs
看具体的信息。 对于 Object 类型的参数(比如写配置项时,假设叫 options
),想对参数对象的各个字段作注释时,首先不能漏了参数名(options)的注释,然后对于各个字段注释,需要带上 options.
作前缀:
/**
* 初始化
*
* @param {Object} options 配置项
* @param {boolean} options.disabled 控件的不可用状态
* @param {(string | HTMLElement)} options.main 控件渲染容器
* @param {(string | HTMLElement)} options.target 计算弹出层相对位置的目标对象
* @param {string} options.prefix 控件class前缀,同时将作为main的class之一
* @param {number} options.index 默认激活的标签索引
*/
JS RULE053 [强制] 参数和返回值注释必须包含类型信息和说明。
错误的注释:
/**
* blablabla
*
* @param foo
* @param bar
*/
需要加上参数类型和说明
/**
* blablabla
*
* @param {number} foo 这是 foo 的说明
* @param {boolean} bar 这是 bar 的说明
*/
JS RULE070 [强制] 变量在使用前必须通过 var
定义。
有三种情况会导致出现该错误。
(一)、使用了非当前文件内定义的全局变量或函数,或者是定义时漏写 var
的变量。
使用了 AMD 的项目,应该通过配置 shim 来把非 AMD 模块伪装成 AMD 模块 require。
未使用 AMD 的项目,作为临时解决方案,需要把该变量或函数标识为 globals:
/* globals foo */
(二)、错误的写法导致出现的全局变量 bar:
var foo = bar = true;
正确写法应该是:
var foo = true;
var bar = foo;
(三)、在代码中,定义的代码在被使用的代码之后(使用变量或函数时,还没出现定义的代码):
function foo() {
bar();
}
var bar = function () {
console.log(baz);
};
var baz = true;
注意:如果 bar
是函数声明则不会报错。
JS RULE071 [强制] 每个 var
只能声明一个变量。
var foo = true,
bar = false;
需要改为:
var foo = true;
var bar = false;
JS RULE072 [强制] 变量必须 即用即声明
,不得在函数或其它形式的代码块起始位置统一声明所有变量。
var foo = function () {
bar();
};
var bar = function () {
// blablabla
};
这种代码的报错主要是因为 bar 的调用在定义之前所致。解决的办法很简单,把 bar 的定义提前:
var bar = function () {
// blablabla
};
var foo = function () {
bar();
};
也可以把 bar 改成函数声明:
var foo = function () {
bar();
};
function bar() {
// blablabla
}
JS RULE073 [强制] 在 Equality Expression 中使用类型严格的 ===
。仅当判断 null 或 undefined 时,允许使用 == null
。
当判断 foo 为 null 或 undefined 时,使用 foo == null
,不是 foo == undefined
。
JS RULE086 [强制] 使用 parseInt
时,必须指定进制。
其实就是为 parseInt
指定第二个参数:
// bad
parseInt(str);
// good
parseInt(str, 10);
主要是防止低级浏览器中的 0
开头的字符默认识别为 8 进制问题:
parseInt('010'); // 8
parseInt('010', 10); // 10
JS RULE089 [强制] 字符串开头和结束使用单引号 '
。
单引号输入时可以少按一个 Shift
键,而在拼写 HTML 字符串时,还可以保留 HTML 属性中的双引号,避免使用 \
转义嵌套的双引号。
var foo = 'bar';
JS RULE094 [建议] 对象创建时,如果一个对象的所有 属性
均可以不添加引号,则所有 属性
不得添加引号。
JS RULE095 [建议] 对象创建时,如果任何一个 属性
需要添加引号,则所有 属性
必须添加 '
。
这两个问题通常和《JS RULE030 [强制] 类的 方法 / 属性
使用 Camel命名法
》相关。
当属性中使用下划线时,不需要添加双引号,但是此时会报 030 的问题。正确的做法是除非有某一属性名出现关键字或非字母数字和 $
、_
之外字符时,可以全部添加引号,否则不允许使用引号。
// 不允许添加引号
var foo = {
'bar': true,
'baz': false
};
// 必须全部添加引号
var foo = {
'bar': true,
'foo-baz': false
};
JS RULE998 [强制] 存在兼容性问题或运行时错误。(%s)
从 Cooder 或 eagle 报的描述中,%s 没有替换为具体的错误信息,所以需要本地运行 fecs
来获取详细的信息再作修改。
JS RULE999 [强制] 语法错误。(%s)
和 RULE998 问题一样,需要本地运行 fecs
来获取详细的信息再作修改。
HTML
HTML RULE012 [强制] 对 HTML5
中规定允许省略的闭合标签,不允许省略闭合标签。
该错误源于对未闭合的标签的检查,示例如下:
<!-- good -->
<ul>
<li>first</li>
<li>second</li>
</ul>
<!-- bad -->
<ul>
<li>first
<li>second
</ul>
不过大多数时候,报告该错误都是因为文件内容并非单纯 HTML 代码,而是某种模板,模板语法破坏了HTML本身的结构,导致一些 HTML 标签被认为没有正确闭合。对于模板文件,建议的做法是修改文件后缀名为 .tpl
或 .tmpl
,避免 HTML 规范检查。如果因为某些原因需要使用 .html
后缀名,可以使用 .tpl.html
,也可以避免检查。
HTML RULE033 [强制] title
必须作为 head
的直接子元素,并紧随 charset
声明之后。
HTML RULE024 [强制] 页面必须使用精简形式,明确指定字符编码。指定字符编码的 meta
必须是 head
的第一个直接子元素。
这两条字面上很好理解,要求 head
中第一个子元素为指定字符编码的 meta
标签,紧随其后是 title
标签。 常见的不规范情况包括:
meta标签未使用精简形式
精简形式:
<meta charset="UTF-8"> `
非精简形式(不符规范):
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
meta
或title
标签位置不正确,规范明确要求了meta
作为head
的第一个直接子元素,且title
紧随其后
这两条字面上很好理解,要求 head
中第一个子元素为指定字符编码的 meta
标签,紧随其后是 title
标签。 常见的不规范情况包括:
meta标签未使用精简形式
精简形式:
<meta charset="UTF-8"> `
非精简形式(不符规范):
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
meta
或title
标签位置不正确,规范明确要求了meta
作为head
的第一个直接子元素,且title
紧随其后
HTML998 [强制] 存在兼容性问题或运行时错误(%s)。
这条 rule 包含两种情况,attr-unsafe-chars
及 id-class-ad-disabled
,因为系统尚未展示错误报告的详细信息,所以这两者目前无法根据错误信息区分。
前者不允许在元素属性值中使用不安全字符,具体为
/[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/
。后者不允许在
id
或class
的值中使用ad
(ad
通过-
或_
与其他字符分隔开,形如:ad-
,xx-ad-xx
,xx-ad
,ad_
,xx_ad_xx
,xx_ad
),否则很大可能会被广告插件过滤。
HTML003 [强制] 使用 4
个空格做为一个缩进层级,不允许使用 2
个空格 或 tab
字符。(Bad indentation (4 instead 0).)
目前的 cooder 会把对内联的 script/style 内容的检查认为是 html 检查结果,所以有时会出现类似
HTML003 [强制] 使用
4
个空格做为一个缩进层级,不允许使用2
个空格 或tab
字符。(Bad indentation (4 instead 0).)
这样的结果。这里的问题实则是内联的 script 内容的缩进错误。
内联的 script/style 内容的缩进要求在标签本身(\/\)基础上不做增加,即:
<!-- bad -->
<script>
alert('!');
</script>
<!-- good -->
<script>
alert('!');
</script>
CSS
CSS RULE002 [强制] 使用 4
个空格做为一个缩进层级,不允许使用 2
个空格 或 tab
字符。
CSS RULE039 [强制] font-weight
属性必须使用数值方式描述。
必须将font-weight
属性值改为数字,数字值 400 相当于关键字 normal,700 等价于 bold,900 等价于 bolder。
CSS RULE046 [强制] 带私有前缀的属性由长到短排列,按冒号位置对齐。
这两条规则看起来似乎有点矛盾,RULE002
说要使用 4
个空格作为缩进,而 RULE046
又说带私有前缀的属性要按长短排列,按冒号的位置来对齐。意思就是带私有前缀的属性可以不使用 4
个空格来作为缩进层级。那么关键词就是 私有前缀
了。但是有时候我们会发现我写的是按照规范来的,为什么还给我报错,而且报的错并不是 RULE002
和 RULE046
。我们来看如下示例:
.ani {
-webkit-animation: spin 2s infinite linear;
-moz-animation: spin 2s infinite linear;
-ms-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
color: #fff;
}
可以看到这段代码是完全符合 RULE002
和 RULE046
的,但是用 fecs
来检测一样会报错出来。 fecs 执行结果如下:
fecs INFO test.css (2 messages)
fecs ERROR → line 4, col 9, rule 998: [强制] 存在兼容性问题或运行时错误。(Current property `-ms-animation` is not existed) (property-not-existed)
fecs ERROR → line 5, col 10, rule 998: [强制] 存在兼容性问题或运行时错误。(Current property `-o-animation` is not existed) (property-not-existed)
信息很明确,我们就知道了其实是 -ms-animation
和 -o-animation
这两个属性不存在导致的。那么问题就来了,如何判断一个带私有前缀的属性是否存在呢?
在工具中,存放带私有前缀的属性的代码在 这里。web 技术发展这么快,各个浏览器厂商也会时不时更新自己产品的实现,当然也包括对一些 CSS
属性的支持等等。因此,这个文件内容也不是一成不变的,也是会时常更新的。如果万一更新得不及时导致代码报错,那么你可以使用行内注释把这两条规则注释掉 /* csshint-disable block-indent vendor-prefixes-sort */
,但是这样写的话,当前你的这个文件就不会得到这两个规则的检测了。因此更好的方式是你提 issue 然后我们更新属性的集合。
其他
当错误超出以上范围,并且认为不需要修复代码,可按以下步骤处理:
安装
fecs
运行
fecs [files] --rule
,记下打印出的错误行尾显示的规则名。在文件头部使用
/* linter-disable ruleName */
来屏蔽对应的规则。其中,JavaScript、CSS 和 HTML 文件分别对应的 linter 为 eslint、csshint 和 htmlcs。如果只需要对指定代码块作规则屏蔽,可以在代码块结束后使用
/* linter-enable ruleName */
来恢复规则检查。
注意:
当省略 ruleName 时,意味着关闭对当前文件的检查,但 ruleName 不存在时,则忽略该条设置。
在 HTML 中,
/*
和*/
应该换成<!--
和-->
。
自动豁免
自动豁免主要是指在 eagle
中自动跳过检查,分为目录、第三方和文件名三种方式。
目录豁免
被检查代码是压缩或编译后的代码、第三方类库、mock 数据或测试文件等,可以归类放置于以下目录内:
- test tests
- dist output
- dep third_party thirdsrc
- mock mocks mockup mockups
- demo
- tool tools
- doc docs
- node_modules bower_components
第三方类库豁免
以下匹配的第三方类库会自动豁免:
- jquery(..+)?.(js|css)$
- tangram.js echarts.js esl.js
- angular.js backbone.js ember.js knockout.js
- bootstrap.js
- yui.js
- zepto.js
- when.js
- moment.js
- html5shiv.js
- typo.css
文件名后缀
对于识别为压缩后文件或模板文件的后缀自动豁免:
- .min.js, .m.js
- .mock.js, .mockup.js
- .min.css, .m.css
- .min.html, .m.html, *.tpl.html