eslint-plugin-light 1.0.22 → 1.0.23
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 +7 -0
- package/README.md +2 -2
- package/lib/rules/img-v-lazy.js +48 -24
- package/lib/test/img-v-lazy.js +87 -0
- package/lib/test/index.js +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## <small>1.0.23 (2026-04-27)</small>
|
|
2
|
+
|
|
3
|
+
* feat(plugin-light): 三元表达式不修复 ([ecabda4](https://github.com/novlan1/plugin-light/commits/ecabda4))
|
|
4
|
+
* chore: update docs ([84adc98](https://github.com/novlan1/plugin-light/commits/84adc98))
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
1
8
|
## <small>1.0.22 (2026-03-24)</small>
|
|
2
9
|
|
|
3
10
|
* feat: add no-complex-style-class rule ([2cc25ee](https://github.com/novlan1/plugin-light/commits/2cc25ee))
|
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<img src="https://img.shields.io/npm/unpacked-size/eslint-plugin-light">
|
|
6
6
|
<img src="https://img.shields.io/npm/v/eslint-plugin-light">
|
|
7
7
|
<img src="https://img.shields.io/npm/l/eslint-plugin-light">
|
|
8
|
-
<img src="https://img.shields.io/
|
|
9
|
-
<img src="https://img.shields.io/
|
|
8
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-blue?logo=typescript&logoColor=white" alt="TypeScript strict">
|
|
9
|
+
<img src="https://img.shields.io/badge/created-2022--01-blue?logo=github&logoColor=white">
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
简单、易用的 ESLint 插件库。
|
package/lib/rules/img-v-lazy.js
CHANGED
|
@@ -9,11 +9,25 @@ module.exports = {
|
|
|
9
9
|
recommended: true,
|
|
10
10
|
},
|
|
11
11
|
fixable: 'code',
|
|
12
|
+
messages: {
|
|
13
|
+
useVLazy: 'Use v-lazy instead of :src for image loading',
|
|
14
|
+
useVLazyManual: 'Use v-lazy instead of :src for image loading (manual replacement required: conditional or fallback expression detected)',
|
|
15
|
+
},
|
|
12
16
|
schema: [],
|
|
13
17
|
},
|
|
14
18
|
create(context) {
|
|
15
19
|
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
16
20
|
|
|
21
|
+
// 判断一个节点是否含有字符串字面量(递归检查 || 链)
|
|
22
|
+
function hasStringLiteral(n) {
|
|
23
|
+
if (!n) return false;
|
|
24
|
+
if (n.type === 'Literal' && typeof n.value === 'string') return true;
|
|
25
|
+
if (n.type === 'LogicalExpression' && n.operator === '||') {
|
|
26
|
+
return hasStringLiteral(n.left) || hasStringLiteral(n.right);
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
17
31
|
const parserServices = getParserServices(context);
|
|
18
32
|
if (!parserServices?.defineTemplateBodyVisitor) {
|
|
19
33
|
return {};
|
|
@@ -32,30 +46,40 @@ module.exports = {
|
|
|
32
46
|
&& attr.key.name.name === 'lazy');
|
|
33
47
|
|
|
34
48
|
if (srcBinding && !hasVLazy) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
const expr = srcBinding.value && srcBinding.value.expression;
|
|
50
|
+
|
|
51
|
+
const isConditional = expr && expr.type === 'ConditionalExpression';
|
|
52
|
+
const isLogicalOr = expr && expr.type === 'LogicalExpression' && expr.operator === '||';
|
|
53
|
+
const isLiteral = expr && expr.type === 'Literal';
|
|
54
|
+
|
|
55
|
+
// 三元表达式 → 手动
|
|
56
|
+
// 顶层字符串字面量 → 手动
|
|
57
|
+
// || 且含字符串字面量 → 用反引号自动修复
|
|
58
|
+
// || 且不含字符串字面量 → 正常双引号自动修复
|
|
59
|
+
if (isConditional || isLiteral) {
|
|
60
|
+
context.report({
|
|
61
|
+
node,
|
|
62
|
+
messageId: 'useVLazyManual',
|
|
63
|
+
});
|
|
64
|
+
} else if (isLogicalOr && hasStringLiteral(expr)) {
|
|
65
|
+
context.report({
|
|
66
|
+
node,
|
|
67
|
+
messageId: 'useVLazy',
|
|
68
|
+
fix(fixer) {
|
|
69
|
+
const srcText = sourceCode.getText(expr);
|
|
70
|
+
return fixer.replaceText(srcBinding, `v-lazy=\`${srcText}\``);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
context.report({
|
|
75
|
+
node,
|
|
76
|
+
messageId: 'useVLazy',
|
|
77
|
+
fix(fixer) {
|
|
78
|
+
const srcText = sourceCode.getText(expr);
|
|
79
|
+
return fixer.replaceText(srcBinding, `v-lazy="${srcText}"`);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
59
83
|
}
|
|
60
84
|
},
|
|
61
85
|
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const { RuleTester } = require('eslint');
|
|
2
|
+
|
|
3
|
+
const rule = require('../rules/img-v-lazy');
|
|
4
|
+
|
|
5
|
+
const FILENAME = 'test.vue';
|
|
6
|
+
|
|
7
|
+
const ruleTester = new RuleTester({
|
|
8
|
+
parser: require.resolve('vue-eslint-parser'),
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 'latest',
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
ruleTester.run('img-v-lazy', rule, {
|
|
16
|
+
valid: [
|
|
17
|
+
// 已使用 v-lazy,合法
|
|
18
|
+
{
|
|
19
|
+
code: '<template><img v-lazy="imgUrl" /></template>',
|
|
20
|
+
filename: FILENAME,
|
|
21
|
+
},
|
|
22
|
+
// 静态 src(非绑定),合法
|
|
23
|
+
{
|
|
24
|
+
code: '<template><img src="https://example.com/image.png" /></template>',
|
|
25
|
+
filename: FILENAME,
|
|
26
|
+
},
|
|
27
|
+
// 已同时有 :src 和 v-lazy,合法
|
|
28
|
+
{
|
|
29
|
+
code: '<template><img :src="imgUrl" v-lazy="imgUrl" /></template>',
|
|
30
|
+
filename: FILENAME,
|
|
31
|
+
},
|
|
32
|
+
// 非 img 标签,合法
|
|
33
|
+
{
|
|
34
|
+
code: '<template><div :src="imgUrl"></div></template>',
|
|
35
|
+
filename: FILENAME,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
invalid: [
|
|
39
|
+
// 普通变量绑定,可自动修复
|
|
40
|
+
{
|
|
41
|
+
code: '<template><img :src="imgUrl" /></template>',
|
|
42
|
+
filename: FILENAME,
|
|
43
|
+
errors: [{ messageId: 'useVLazy' }],
|
|
44
|
+
output: '<template><img v-lazy="imgUrl" /></template>',
|
|
45
|
+
},
|
|
46
|
+
// 成员表达式,可自动修复
|
|
47
|
+
{
|
|
48
|
+
code: '<template><img :src="item.imageUrl" /></template>',
|
|
49
|
+
filename: FILENAME,
|
|
50
|
+
errors: [{ messageId: 'useVLazy' }],
|
|
51
|
+
output: '<template><img v-lazy="item.imageUrl" /></template>',
|
|
52
|
+
},
|
|
53
|
+
// 字符串字面量,需手动替换(无 output / fix)
|
|
54
|
+
{
|
|
55
|
+
code: '<template><img :src="\'https://example.com/img.png\'" /></template>',
|
|
56
|
+
filename: FILENAME,
|
|
57
|
+
errors: [{ messageId: 'useVLazyManual' }],
|
|
58
|
+
},
|
|
59
|
+
// 三元表达式,需手动替换(无 output / fix)
|
|
60
|
+
{
|
|
61
|
+
code: '<template><img :src="item.img ? item.img : \'https://example.com/default.png\'" /></template>',
|
|
62
|
+
filename: FILENAME,
|
|
63
|
+
errors: [{ messageId: 'useVLazyManual' }],
|
|
64
|
+
},
|
|
65
|
+
// 逻辑或 + 字符串字面量,用反引号自动修复
|
|
66
|
+
{
|
|
67
|
+
code: '<template><img :src="item.img || \'https://example.com/default.png\'" /></template>',
|
|
68
|
+
filename: FILENAME,
|
|
69
|
+
errors: [{ messageId: 'useVLazy' }],
|
|
70
|
+
output: '<template><img v-lazy=`item.img || \'https://example.com/default.png\'` /></template>',
|
|
71
|
+
},
|
|
72
|
+
// 逻辑或 + 两侧都是变量,正常双引号自动修复
|
|
73
|
+
{
|
|
74
|
+
code: '<template><img :src="item.img || fallbackImg" /></template>',
|
|
75
|
+
filename: FILENAME,
|
|
76
|
+
errors: [{ messageId: 'useVLazy' }],
|
|
77
|
+
output: '<template><img v-lazy="item.img || fallbackImg" /></template>',
|
|
78
|
+
},
|
|
79
|
+
// v-bind:src 写法,可自动修复
|
|
80
|
+
{
|
|
81
|
+
code: '<template><img v-bind:src="imgUrl" /></template>',
|
|
82
|
+
filename: FILENAME,
|
|
83
|
+
errors: [{ messageId: 'useVLazy' }],
|
|
84
|
+
output: '<template><img v-lazy="imgUrl" /></template>',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
});
|
package/lib/test/index.js
CHANGED