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.
Files changed (3) hide show
  1. package/README.md +32 -1
  2. package/dist/index.mjs +48 -14
  3. 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
+ [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](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.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
- return {
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
- return {
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 expressions
513
+ // Check for ref property access in template strings (for non-SFC files)
488
514
  MemberExpression(node) {
489
- if (isInVueTemplateString(node) && node.object.type === "Identifier" && node.property.type === "Identifier" && isRefProperty(node.object.name, node.property.name)) {
490
- const parent = node.parent;
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
- return {
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
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-harlanzw",
3
3
  "type": "module",
4
- "version": "0.0.1",
4
+ "version": "0.0.2",
5
5
  "description": "Harlan's opinionated ESLint rules",
6
6
  "author": "Harlan Wilton <harlan@harlanzw.com>",
7
7
  "license": "MIT",