eslint-plugin-light 1.0.15 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +91 -5
- package/lib/rules/no-decimal-in-brackets.js +53 -0
- package/lib/rules/no-direct-img-src.js +43 -0
- package/lib/rules/no-todo-comment.js +42 -0
- package/lib/test/no-decimal-in-brackets.js +35 -0
- package/lib/test/no-direct-img-src.js +39 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## <small>1.0.18 (2025-08-08)</small>
|
|
2
|
+
|
|
3
|
+
* feat(eslint): add no-decimal-in-brackets rule ([a4c2b0d](https://github.com/novlan1/plugin-light/commits/a4c2b0d))
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## <small>1.0.17 (2025-07-23)</small>
|
|
8
|
+
|
|
9
|
+
* feat(eslint-plugin): add no-direct-img-src rule ([4223182](https://github.com/novlan1/plugin-light/commits/4223182))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## <small>1.0.16 (2025-07-18)</small>
|
|
14
|
+
|
|
15
|
+
* feat(eslint): add no-todo-comment rule ([8b555b7](https://github.com/novlan1/plugin-light/commits/8b555b7))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
1
19
|
## <small>1.0.15 (2025-06-16)</small>
|
|
2
20
|
|
|
3
21
|
* feat(eslint-plugin-light): add img v-lazy ([5807b47](https://github.com/novlan1/plugin-light/commits/5807b47))
|
package/README.md
CHANGED
|
@@ -205,14 +205,14 @@ Bad case:
|
|
|
205
205
|
|
|
206
206
|
```js
|
|
207
207
|
// bad
|
|
208
|
-
import { pubg_fateClient } from 'src/api/git.
|
|
208
|
+
import { pubg_fateClient } from 'src/api/git.aow.com/itrpcprotocol/esport/esport_cgi/pubg_fate/pubg_fate.http';
|
|
209
209
|
```
|
|
210
210
|
|
|
211
211
|
Good case:
|
|
212
212
|
|
|
213
213
|
```js
|
|
214
214
|
// good
|
|
215
|
-
import { QueryGameListHomePageClient } from 'src/api/git.
|
|
215
|
+
import { QueryGameListHomePageClient } from 'src/api/git.aow.com/itrpcprotocol/esport/esport_cgi/pubg_fate/pubg_fate/QueryGameListHomePage.http';
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
Usage:
|
|
@@ -242,14 +242,14 @@ module.exports = {
|
|
|
242
242
|
rules: {
|
|
243
243
|
'light/no-import-all-in-one-api': [2, {
|
|
244
244
|
excludes: [
|
|
245
|
-
'src/api/git.
|
|
245
|
+
'src/api/git.aow.com/itrpcprotocol/esport/esport_cgi/pubg_fate/pubg_fate.http',
|
|
246
246
|
]
|
|
247
247
|
}],
|
|
248
248
|
},
|
|
249
249
|
}
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
-
下面是一个案例,根据这个规则,对一个线上项目进行改造。仅仅改动了[几个文件的几行引入语句](https://git.
|
|
252
|
+
下面是一个案例,根据这个规则,对一个线上项目进行改造。仅仅改动了[几个文件的几行引入语句](https://git.aow.com/pmd-mobile/match/gp-next/commit/20e0050fe10ed767dcb5d77dca76a9b51c23820e),就减少了主包 `50KB`,效果立竿见影。
|
|
253
253
|
|
|
254
254
|
之前:
|
|
255
255
|
|
|
@@ -414,7 +414,7 @@ module.exports = {
|
|
|
414
414
|
|
|
415
415
|
### 3.12. img-v-lazy
|
|
416
416
|
|
|
417
|
-
强制 `img` 标签使用 `v-lazy` 而不是 `:src
|
|
417
|
+
强制 `img` 标签使用 `v-lazy` 而不是 `:src`,可用于 Vue 项目中。
|
|
418
418
|
|
|
419
419
|
Usage:
|
|
420
420
|
|
|
@@ -431,6 +431,92 @@ module.exports = {
|
|
|
431
431
|
}
|
|
432
432
|
```
|
|
433
433
|
|
|
434
|
+
### 3.13. no-direct-img-src
|
|
435
|
+
|
|
436
|
+
在 `jsx/tsx` 中禁止直接使用 `img src`,必须使用封装的 [`CdnImage` 组件](https://novlan1.github.io/docs/press-pix/zh-CN/cdn-image.html),可用于 React 项目中。
|
|
437
|
+
|
|
438
|
+
与 [img-v-lazy 规则](#_3-12-img-v-lazy) 类似,都是为了防止直接使用 COS 图片,而不是 CDN 图片。
|
|
439
|
+
|
|
440
|
+
Usage:
|
|
441
|
+
|
|
442
|
+
```js
|
|
443
|
+
// .eslintrc.js
|
|
444
|
+
|
|
445
|
+
module.exports = {
|
|
446
|
+
plugins: [
|
|
447
|
+
'light',
|
|
448
|
+
],
|
|
449
|
+
rules: {
|
|
450
|
+
'light/no-direct-img-src': 2,
|
|
451
|
+
|
|
452
|
+
// 传入参数
|
|
453
|
+
'light/no-direct-img-src': [2, {
|
|
454
|
+
componentName: 'MyCdnImage',
|
|
455
|
+
}],
|
|
456
|
+
},
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
配置选项:
|
|
461
|
+
|
|
462
|
+
| 字段 | 说明 | 默认值 |
|
|
463
|
+
| ------------- | ---------------------- | ---------- |
|
|
464
|
+
| componentName | 提示词中的自定义组件名 | `CdnImage` |
|
|
465
|
+
|
|
466
|
+
### 3.14. no-todo-comment
|
|
467
|
+
|
|
468
|
+
不允许存在 TODO。可防止调试代码被意外带到线上。
|
|
469
|
+
|
|
470
|
+
Usage:
|
|
471
|
+
|
|
472
|
+
```js
|
|
473
|
+
// .eslintrc.js
|
|
474
|
+
|
|
475
|
+
module.exports = {
|
|
476
|
+
plugins: [
|
|
477
|
+
'light',
|
|
478
|
+
],
|
|
479
|
+
rules: {
|
|
480
|
+
'light/no-todo-comment': 2,
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
配置选项:
|
|
486
|
+
|
|
487
|
+
| 字段 | 说明 | 默认值 |
|
|
488
|
+
| ------- | ---------- | ------- |
|
|
489
|
+
| keyword | 检查关键词 | `TODO:` |
|
|
490
|
+
|
|
491
|
+
### 3.15. no-decimal-in-brackets
|
|
492
|
+
|
|
493
|
+
禁止在方括号类名中使用小数点。背景:
|
|
494
|
+
|
|
495
|
+
>小程序中不能使用 `pr-[.28rem]` 这种,可以使用 `pr-1.12`,同时在`tailwind.config.js` 中配置下 `theme.extend.padding = {1.12: '.28rem'}`。
|
|
496
|
+
>
|
|
497
|
+
>原因是`uni-app`会把`class`中的`[.`解析成`\[\`放到`wxss`中,导致编译错误。
|
|
498
|
+
|
|
499
|
+
Usage:
|
|
500
|
+
|
|
501
|
+
```js
|
|
502
|
+
// .eslintrc.js
|
|
503
|
+
|
|
504
|
+
module.exports = {
|
|
505
|
+
plugins: [
|
|
506
|
+
'light',
|
|
507
|
+
],
|
|
508
|
+
rules: {
|
|
509
|
+
'light/no-decimal-in-brackets': 2,
|
|
510
|
+
},
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
配置选项:
|
|
515
|
+
|
|
516
|
+
| 字段 | 说明 | 默认值 |
|
|
517
|
+
| ------ | -------- | ----------------------------------- |
|
|
518
|
+
| regexp | 匹配正则 | `/\[[^\](]*\.\d+[a-zA-Z]+[^\]]*\]/` |
|
|
519
|
+
|
|
434
520
|
## 4. 更新日志
|
|
435
521
|
|
|
436
522
|
[点此查看](./CHANGELOG.md)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const utils = require('eslint-plugin-vue/lib/utils');
|
|
2
|
+
const TEST_REGEX = /\[[^\](]*\.\d+[a-zA-Z]+[^\]]*\]/;
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: '禁止在方括号类名中使用小数点',
|
|
10
|
+
category: 'Best Practices',
|
|
11
|
+
recommended: true,
|
|
12
|
+
},
|
|
13
|
+
schema: [
|
|
14
|
+
{
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: {
|
|
17
|
+
regexp: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
default: TEST_REGEX,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
create(context) {
|
|
27
|
+
const options = context.options[0] || {};
|
|
28
|
+
const regex = options.regexp ?? TEST_REGEX;
|
|
29
|
+
|
|
30
|
+
return utils.defineTemplateBodyVisitor(context, {
|
|
31
|
+
'VAttribute[key.name=\'class\']'(node) {
|
|
32
|
+
if (!node.value || node.value.type !== 'VLiteral') return;
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
const classValue = node.value.value.trim();
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const classNames = classValue.split(/\s+/).filter(c => c.trim());
|
|
39
|
+
const errorList = classNames.filter(item => regex.test(item));
|
|
40
|
+
|
|
41
|
+
if (!errorList?.length) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
context.report({
|
|
46
|
+
node,
|
|
47
|
+
loc: node.value.loc,
|
|
48
|
+
message: `禁止在方括号类名中使用小数点: ${errorList.join(', ')}`,
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const DEFAULT_COMPONENT_NAME = 'CdnImage';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'problem',
|
|
6
|
+
docs: {
|
|
7
|
+
description: '禁止直接使用 img src,必须使用封装的自定义组件',
|
|
8
|
+
category: 'Best Practices',
|
|
9
|
+
recommended: true,
|
|
10
|
+
},
|
|
11
|
+
fixable: 'code',
|
|
12
|
+
schema: [
|
|
13
|
+
{
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
componentName: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
default: DEFAULT_COMPONENT_NAME,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
create(context) {
|
|
26
|
+
return {
|
|
27
|
+
JSXOpeningElement(node) {
|
|
28
|
+
if (node.name.name === 'img') {
|
|
29
|
+
const srcAttribute = node.attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'src');
|
|
30
|
+
const options = context.options[0] || {};
|
|
31
|
+
const componentName = options.componentName ?? DEFAULT_COMPONENT_NAME;
|
|
32
|
+
|
|
33
|
+
if (srcAttribute) {
|
|
34
|
+
context.report({
|
|
35
|
+
node,
|
|
36
|
+
message: `禁止直接使用 img src,必须使用封装的 ${componentName} 组件`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const DEFAULT_KEYWORD = 'TODO:';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: 'problem',
|
|
6
|
+
docs: {
|
|
7
|
+
description: '禁止使用未规范的TODO注释',
|
|
8
|
+
category: 'Best Practices',
|
|
9
|
+
recommended: true,
|
|
10
|
+
},
|
|
11
|
+
schema: [
|
|
12
|
+
{
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
keyword: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
default: DEFAULT_KEYWORD,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
create(context) {
|
|
25
|
+
const sourceCode = context.getSourceCode();
|
|
26
|
+
const comments = sourceCode.getAllComments();
|
|
27
|
+
|
|
28
|
+
comments.forEach((comment) => {
|
|
29
|
+
const options = context.options[0] || {};
|
|
30
|
+
const keyword = options.keyword ?? DEFAULT_KEYWORD;
|
|
31
|
+
|
|
32
|
+
if (comment.value.includes(keyword)) {
|
|
33
|
+
context.report({
|
|
34
|
+
node: comment,
|
|
35
|
+
message: '不允许 TODO 存在',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const { RuleTester } = require('eslint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../rules/no-decimal-in-brackets');
|
|
4
|
+
|
|
5
|
+
const ERROR_MESSAGE = '禁止在方括号类名中使用小数点';
|
|
6
|
+
const ruleTester = new RuleTester({
|
|
7
|
+
parser: require.resolve('vue-eslint-parser'),
|
|
8
|
+
parserOptions: {
|
|
9
|
+
ecmaVersion: 'latest',
|
|
10
|
+
sourceType: 'module',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
ruleTester.run('no-decimal-in-brackets', rule, {
|
|
15
|
+
valid: [
|
|
16
|
+
'<template><div class="pl-[1rem]"></div></template>',
|
|
17
|
+
|
|
18
|
+
'<template><div class="pl-[0.1]"></div></template>', // 允许小数点后无字母
|
|
19
|
+
'<template><div class="bg-[red]"></div></template>', // 允许纯字母
|
|
20
|
+
'<template><div class="text-[24]"></div></template>', // 允许纯数字
|
|
21
|
+
|
|
22
|
+
'<template><div class="bg-[rgba(0,0,0,.5)]"></div></template>', // 允许函数中的小数点
|
|
23
|
+
'<template><div class="opacity-[.5]"></div></template>', // 允许小数点前无数字
|
|
24
|
+
],
|
|
25
|
+
invalid: [
|
|
26
|
+
{
|
|
27
|
+
code: '<template><div class=\'pl-[0.1rem]\'></div></template>',
|
|
28
|
+
errors: [{ message: `${ERROR_MESSAGE}: pl-[0.1rem]` }],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: '<template><div class=\'text-[0.1rem] pl-[22.1px]\'></div></template>',
|
|
32
|
+
errors: [{ message: `${ERROR_MESSAGE}: text-[0.1rem], pl-[22.1px]` }],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const { RuleTester } = require('eslint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../rules/no-direct-img-src');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const ruleTester = new RuleTester({
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaVersion: 'latest',
|
|
9
|
+
sourceType: 'module',
|
|
10
|
+
ecmaFeatures: {
|
|
11
|
+
jsx: true,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const ERROR_MESSAGE = '禁止直接使用 img src,必须使用封装的 CdnImage 组件';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
ruleTester.run('no-direct-img-src', rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{
|
|
22
|
+
code: '<CdnImage src="image.png" alt="example" />',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
code: '<div><CdnImage src="image.jpg" /></div>',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
invalid: [
|
|
29
|
+
{
|
|
30
|
+
code: '<img src="image.png" alt="example" />',
|
|
31
|
+
errors: [{ message: ERROR_MESSAGE }],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
code: '<img src={require("./image.jpg")} className="img" />',
|
|
35
|
+
errors: [{ message: ERROR_MESSAGE }],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-light",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"description": "Simple Eslint Plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"eslint-plugin-eslint-plugin": "^4.0.1",
|
|
39
39
|
"eslint-plugin-node": "^11.1.0",
|
|
40
40
|
"mocha": "^9.1.3",
|
|
41
|
-
"standard-version": "^9.5.0"
|
|
41
|
+
"standard-version": "^9.5.0",
|
|
42
|
+
"vue-eslint-parser": "^9.4.3"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"@babel/eslint-parser": ">=6",
|