eslint-plugin-harlanzw 0.0.1 → 0.0.2
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/README.md +32 -1
- package/dist/index.mjs +48 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,12 @@ Harlan's ESLint rules for Vue projects.
|
|
|
16
16
|
</table>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
+
## Playground
|
|
20
|
+
|
|
21
|
+
Try the rules in action with a Nuxt ESLint interactive playground:
|
|
22
|
+
|
|
23
|
+
[](https://stackblitz.com/github/harlan-zw/eslint-plugin-harlanzw/tree/main/playground)
|
|
24
|
+
|
|
19
25
|
## Rules
|
|
20
26
|
|
|
21
27
|
> **Note:** These rules are experimental and may change. They will be submitted to the official Vue ESLint plugin for consideration.
|
|
@@ -64,6 +70,27 @@ export default antfu(
|
|
|
64
70
|
)
|
|
65
71
|
```
|
|
66
72
|
|
|
73
|
+
### With Nuxt ESLint
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// eslint.config.mjs
|
|
77
|
+
import harlanzw from 'eslint-plugin-harlanzw'
|
|
78
|
+
import withNuxt from './.nuxt/eslint.config.mjs'
|
|
79
|
+
|
|
80
|
+
export default withNuxt([{
|
|
81
|
+
plugins: {
|
|
82
|
+
harlanzw
|
|
83
|
+
},
|
|
84
|
+
rules: {
|
|
85
|
+
'harlanzw/vue-no-faux-composables': 'error',
|
|
86
|
+
'harlanzw/vue-no-nested-reactivity': 'error',
|
|
87
|
+
'harlanzw/vue-no-passing-refs-as-props': 'error',
|
|
88
|
+
'harlanzw/vue-no-ref-access-in-templates': 'error',
|
|
89
|
+
'harlanzw/vue-no-torefs-on-props': 'error'
|
|
90
|
+
}
|
|
91
|
+
}])
|
|
92
|
+
```
|
|
93
|
+
|
|
67
94
|
### Standalone Usage
|
|
68
95
|
|
|
69
96
|
Add the plugin to your ESLint configuration:
|
|
@@ -71,9 +98,14 @@ Add the plugin to your ESLint configuration:
|
|
|
71
98
|
```js
|
|
72
99
|
// eslint.config.js
|
|
73
100
|
import harlanzw from 'eslint-plugin-harlanzw'
|
|
101
|
+
import vueParser from 'vue-eslint-parser'
|
|
74
102
|
|
|
75
103
|
export default [
|
|
76
104
|
{
|
|
105
|
+
files: ['**/*.vue'],
|
|
106
|
+
languageOptions: {
|
|
107
|
+
parser: vueParser
|
|
108
|
+
},
|
|
77
109
|
plugins: {
|
|
78
110
|
harlanzw
|
|
79
111
|
},
|
|
@@ -88,7 +120,6 @@ export default [
|
|
|
88
120
|
]
|
|
89
121
|
```
|
|
90
122
|
|
|
91
|
-
|
|
92
123
|
## Sponsors
|
|
93
124
|
|
|
94
125
|
<p align="center">
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = "0.0.
|
|
1
|
+
const version = "0.0.1";
|
|
2
2
|
|
|
3
3
|
const hasDocs = [
|
|
4
4
|
"use-composables-must-use-reactivity",
|
|
@@ -409,7 +409,7 @@ const vueNoNestedReactivity = createEslintRule({
|
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
|
-
|
|
412
|
+
const scriptVisitor = {
|
|
413
413
|
Program() {
|
|
414
414
|
vueImports.clear();
|
|
415
415
|
reactiveVariables.clear();
|
|
@@ -442,6 +442,20 @@ const vueNoNestedReactivity = createEslintRule({
|
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
444
|
};
|
|
445
|
+
const templateVisitor = {
|
|
446
|
+
// Check for nested reactivity in Vue SFC templates
|
|
447
|
+
CallExpression(node) {
|
|
448
|
+
const reactiveType = isReactiveCall(node);
|
|
449
|
+
if (reactiveType) {
|
|
450
|
+
checkForNestedReactivity(node, reactiveType);
|
|
451
|
+
}
|
|
452
|
+
checkComputedCallback(node);
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
if (isVueParser(context)) {
|
|
456
|
+
return defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor);
|
|
457
|
+
}
|
|
458
|
+
return scriptVisitor;
|
|
445
459
|
}
|
|
446
460
|
});
|
|
447
461
|
|
|
@@ -465,7 +479,19 @@ const vueNoPassingRefsAsProps = createEslintRule({
|
|
|
465
479
|
const properties = refProperties.get(objectName);
|
|
466
480
|
return properties?.has(propertyName) ?? false;
|
|
467
481
|
}
|
|
468
|
-
|
|
482
|
+
function checkMemberExpression(node) {
|
|
483
|
+
if (node.object.type === "Identifier" && node.property.type === "Identifier" && isRefProperty(node.object.name, node.property.name)) {
|
|
484
|
+
const parent = node.parent;
|
|
485
|
+
if (parent?.type === "MemberExpression" && parent.property.type === "Identifier" && parent.property.name === "value") {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
context.report({
|
|
489
|
+
node,
|
|
490
|
+
messageId: "noPassingRefsAsProps"
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const scriptVisitor = {
|
|
469
495
|
Program() {
|
|
470
496
|
refProperties.clear();
|
|
471
497
|
},
|
|
@@ -484,20 +510,20 @@ const vueNoPassingRefsAsProps = createEslintRule({
|
|
|
484
510
|
}
|
|
485
511
|
}
|
|
486
512
|
},
|
|
487
|
-
// Check for ref property access in template
|
|
513
|
+
// Check for ref property access in template strings (for non-SFC files)
|
|
488
514
|
MemberExpression(node) {
|
|
489
|
-
if (isInVueTemplateString(node)
|
|
490
|
-
|
|
491
|
-
if (parent?.type === "MemberExpression" && parent.property.type === "Identifier" && parent.property.name === "value") {
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
context.report({
|
|
495
|
-
node,
|
|
496
|
-
messageId: "noPassingRefsAsProps"
|
|
497
|
-
});
|
|
515
|
+
if (isInVueTemplateString(node)) {
|
|
516
|
+
checkMemberExpression(node);
|
|
498
517
|
}
|
|
499
518
|
}
|
|
500
519
|
};
|
|
520
|
+
if (isVueParser(context)) {
|
|
521
|
+
return defineTemplateBodyVisitor(context, {
|
|
522
|
+
// Check for ref property access in Vue SFC templates
|
|
523
|
+
MemberExpression: checkMemberExpression
|
|
524
|
+
}, scriptVisitor);
|
|
525
|
+
}
|
|
526
|
+
return scriptVisitor;
|
|
501
527
|
}
|
|
502
528
|
});
|
|
503
529
|
|
|
@@ -645,7 +671,7 @@ const vueNoTorefsOnProps = createEslintRule({
|
|
|
645
671
|
}
|
|
646
672
|
}
|
|
647
673
|
}
|
|
648
|
-
|
|
674
|
+
const scriptVisitor = {
|
|
649
675
|
Program() {
|
|
650
676
|
propsVariables.clear();
|
|
651
677
|
},
|
|
@@ -665,6 +691,14 @@ const vueNoTorefsOnProps = createEslintRule({
|
|
|
665
691
|
checkToRefsCall(node);
|
|
666
692
|
}
|
|
667
693
|
};
|
|
694
|
+
const templateVisitor = {
|
|
695
|
+
// Check for toRefs calls in Vue SFC templates
|
|
696
|
+
CallExpression: checkToRefsCall
|
|
697
|
+
};
|
|
698
|
+
if (isVueParser(context)) {
|
|
699
|
+
return defineTemplateBodyVisitor(context, templateVisitor, scriptVisitor);
|
|
700
|
+
}
|
|
701
|
+
return scriptVisitor;
|
|
668
702
|
}
|
|
669
703
|
});
|
|
670
704
|
|