@kouts/eslint-config 3.0.3 → 3.0.4

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 CHANGED
@@ -112,6 +112,68 @@ Ad the following settings to your VS Code project settings for autofix on save:
112
112
  - [eslint-plugin-simple-import-sort](https://github.com/lydell/eslint-plugin-simple-import-sort) for auto-fixing imports order
113
113
  - [eslint-plugin-vitest](https://github.com/vitest-dev/eslint-plugin-vitest) for linting Vitest test files
114
114
 
115
+ ## Vue-specific Rules
116
+
117
+ This configuration extends the [ESLint plugin Vue recommended preset](https://eslint.vuejs.org/rules/#priority-c-recommended-potentially-dangerous-patterns) but makes several modifications to enhance code quality and consistency in Vue components.
118
+
119
+ ### Disabled Rules
120
+
121
+ - `vue/max-attributes-per-line`: Turned off to allow flexibility in attribute formatting
122
+ - `vue/singleline-html-element-content-newline`: Turned off for cleaner code with fewer line breaks
123
+
124
+ ### Strengthened Rules (set to 'error')
125
+
126
+ - `vue/attributes-order`: Enforces consistent order of component attributes
127
+ - `vue/block-order`: Enforces consistent order of component blocks
128
+ - `vue/no-lone-template`: Prevents unnecessary template wrappers
129
+ - `vue/no-multiple-slot-args`: Prevents passing multiple arguments to slots
130
+ - `vue/no-v-html`: Prevents use of v-html to mitigate XSS risks
131
+ - `vue/order-in-components`: Enforces consistent order of component options
132
+ - `vue/this-in-template`: Prevents usage of this in templates
133
+ - `vue/require-prop-types`: Requires type definitions for props
134
+ - `vue/component-name-in-template-casing`: Enforces PascalCase for component names in templates
135
+ - `vue/no-static-inline-styles`: Prevents inline styles in templates
136
+ - `vue/require-explicit-emits`: Requires explicit emit declarations
137
+ - `vue/require-name-property`: Requires components to have a name property
138
+ - `vue/html-self-closing`: Enforces self-closing style for components with no content
139
+ - `vue/dot-notation`: Enforces dot notation where possible in templates
140
+
141
+ ### Custom Vue Rules
142
+
143
+ - `kouts/vue-require-name-in-setup`: Enforces that Vue components using `<script setup>` must have a component name.
144
+
145
+ ### Customizing/Disabling Vue Rules
146
+
147
+ You can customize or disable any of these rules in your ESLint config:
148
+
149
+ ```js
150
+ // eslint.config.js
151
+ import { config } from '@kouts/eslint-config'
152
+
153
+ export default [
154
+ ...config(),
155
+ {
156
+ rules: {
157
+ // Disable custom rule
158
+ 'kouts/vue-require-name-in-setup': 'off',
159
+
160
+ // Modify strengthened Vue rules
161
+ 'vue/attributes-order': 'warn',
162
+ 'vue/no-v-html': 'off',
163
+
164
+ // Re-enable rules that were turned off
165
+ 'vue/max-attributes-per-line': [
166
+ 'error',
167
+ {
168
+ singleline: { max: 3 },
169
+ multiline: { max: 1 },
170
+ },
171
+ ],
172
+ },
173
+ },
174
+ ]
175
+ ```
176
+
115
177
  ## License
116
178
 
117
179
  [MIT](http://opensource.org/licenses/MIT)
package/dist/index.cjs CHANGED
@@ -8,6 +8,55 @@ var pluginSimpleImportSort = require('eslint-plugin-simple-import-sort');
8
8
  var neostandard = require('neostandard');
9
9
  var pluginVue = require('eslint-plugin-vue');
10
10
 
11
+ const rule = {
12
+ meta: {
13
+ type: "suggestion",
14
+ docs: {
15
+ description: "Require defineOptions with name attribute in script setup Vue components",
16
+ category: "Best Practices",
17
+ recommended: true
18
+ },
19
+ schema: []
20
+ },
21
+ create(context) {
22
+ let hasDefineOptionsWithName = false;
23
+ return {
24
+ // We'll assume every Vue file with script setup needs a defineOptions name
25
+ // Check for defineOptions function calls
26
+ 'CallExpression[callee.name="defineOptions"]'(node) {
27
+ if (node.arguments?.length && node.arguments[0]?.type === "ObjectExpression") {
28
+ const properties = node.arguments[0].properties || [];
29
+ for (const prop of properties) {
30
+ if (prop.type === "Property" && prop.key?.type === "Identifier" && prop.key?.name === "name") {
31
+ hasDefineOptionsWithName = true;
32
+ break;
33
+ }
34
+ }
35
+ }
36
+ },
37
+ // At the end of the file, report if we don't have defineOptions with name
38
+ "Program:exit"(node) {
39
+ const filename = context.physicalFilename;
40
+ const isVueFile = filename.endsWith(".vue");
41
+ if (isVueFile && !hasDefineOptionsWithName) {
42
+ const sourceCode = context.sourceCode.getText();
43
+ const hasScriptSetup = /<script\s+setup/.test(sourceCode);
44
+ if (hasScriptSetup) {
45
+ context.report({
46
+ node,
47
+ message: 'Component name is required. Add defineOptions({ name: "YourComponentName" }) to your <script setup>'
48
+ });
49
+ }
50
+ }
51
+ }
52
+ };
53
+ }
54
+ };
55
+
56
+ var customRules = {
57
+ "vue-require-name-in-setup": rule
58
+ };
59
+
11
60
  const typescript = [
12
61
  ...neostandard.plugins["typescript-eslint"].configs.recommended,
13
62
  {
@@ -71,6 +120,8 @@ const vue = (options) => {
71
120
  files: ["*.vue", "**/*.vue"],
72
121
  ...languageOptions,
73
122
  rules: {
123
+ // Custom rules
124
+ "kouts/vue-require-name-in-setup": "error",
74
125
  // Overrides for vue/(vue3-)recommended preset
75
126
  "vue/max-attributes-per-line": "off",
76
127
  "vue/singleline-html-element-content-newline": "off",
@@ -113,6 +164,7 @@ const vue = (options) => {
113
164
  return config;
114
165
  };
115
166
 
167
+ const customRulesPlugin = { name: "kouts", rules: customRules };
116
168
  const config = (options) => {
117
169
  const opts = {
118
170
  noJsx: true,
@@ -125,6 +177,13 @@ const config = (options) => {
125
177
  ...options
126
178
  };
127
179
  const linterConfig = [
180
+ // Custom rules plugin
181
+ {
182
+ name: "kouts/custom-rules",
183
+ plugins: {
184
+ kouts: customRulesPlugin
185
+ }
186
+ },
128
187
  {
129
188
  name: "kouts/ignores",
130
189
  ignores: [
package/dist/index.js CHANGED
@@ -7,6 +7,55 @@ import neostandard, { plugins, resolveIgnoresFromGitignore } from 'neostandard';
7
7
  export { plugins } from 'neostandard';
8
8
  import pluginVue from 'eslint-plugin-vue';
9
9
 
10
+ const rule = {
11
+ meta: {
12
+ type: "suggestion",
13
+ docs: {
14
+ description: "Require defineOptions with name attribute in script setup Vue components",
15
+ category: "Best Practices",
16
+ recommended: true
17
+ },
18
+ schema: []
19
+ },
20
+ create(context) {
21
+ let hasDefineOptionsWithName = false;
22
+ return {
23
+ // We'll assume every Vue file with script setup needs a defineOptions name
24
+ // Check for defineOptions function calls
25
+ 'CallExpression[callee.name="defineOptions"]'(node) {
26
+ if (node.arguments?.length && node.arguments[0]?.type === "ObjectExpression") {
27
+ const properties = node.arguments[0].properties || [];
28
+ for (const prop of properties) {
29
+ if (prop.type === "Property" && prop.key?.type === "Identifier" && prop.key?.name === "name") {
30
+ hasDefineOptionsWithName = true;
31
+ break;
32
+ }
33
+ }
34
+ }
35
+ },
36
+ // At the end of the file, report if we don't have defineOptions with name
37
+ "Program:exit"(node) {
38
+ const filename = context.physicalFilename;
39
+ const isVueFile = filename.endsWith(".vue");
40
+ if (isVueFile && !hasDefineOptionsWithName) {
41
+ const sourceCode = context.sourceCode.getText();
42
+ const hasScriptSetup = /<script\s+setup/.test(sourceCode);
43
+ if (hasScriptSetup) {
44
+ context.report({
45
+ node,
46
+ message: 'Component name is required. Add defineOptions({ name: "YourComponentName" }) to your <script setup>'
47
+ });
48
+ }
49
+ }
50
+ }
51
+ };
52
+ }
53
+ };
54
+
55
+ var customRules = {
56
+ "vue-require-name-in-setup": rule
57
+ };
58
+
10
59
  const typescript = [
11
60
  ...plugins["typescript-eslint"].configs.recommended,
12
61
  {
@@ -70,6 +119,8 @@ const vue = (options) => {
70
119
  files: ["*.vue", "**/*.vue"],
71
120
  ...languageOptions,
72
121
  rules: {
122
+ // Custom rules
123
+ "kouts/vue-require-name-in-setup": "error",
73
124
  // Overrides for vue/(vue3-)recommended preset
74
125
  "vue/max-attributes-per-line": "off",
75
126
  "vue/singleline-html-element-content-newline": "off",
@@ -112,6 +163,7 @@ const vue = (options) => {
112
163
  return config;
113
164
  };
114
165
 
166
+ const customRulesPlugin = { name: "kouts", rules: customRules };
115
167
  const config = (options) => {
116
168
  const opts = {
117
169
  noJsx: true,
@@ -124,6 +176,13 @@ const config = (options) => {
124
176
  ...options
125
177
  };
126
178
  const linterConfig = [
179
+ // Custom rules plugin
180
+ {
181
+ name: "kouts/custom-rules",
182
+ plugins: {
183
+ kouts: customRulesPlugin
184
+ }
185
+ },
127
186
  {
128
187
  name: "kouts/ignores",
129
188
  ignores: [
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@kouts/eslint-config",
3
3
  "type": "module",
4
- "version": "3.0.3",
5
- "packageManager": "pnpm@10.9.0",
4
+ "version": "3.0.4",
5
+ "packageManager": "pnpm@10.10.0",
6
6
  "engines": {
7
7
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
8
8
  },
@@ -70,13 +70,13 @@
70
70
  "url": "git+https://github.com/kouts/eslint-config.git"
71
71
  },
72
72
  "dependencies": {
73
- "@eslint/js": "^9.25.1",
74
- "@vitest/eslint-plugin": "^1.1.43",
73
+ "@eslint/js": "^9.26.0",
74
+ "@vitest/eslint-plugin": "^1.1.44",
75
75
  "eslint-config-prettier": "^10.1.2",
76
76
  "eslint-plugin-html": "^8.1.2",
77
77
  "eslint-plugin-prettier": "^5.2.6",
78
78
  "eslint-plugin-simple-import-sort": "^12.1.1",
79
- "eslint-plugin-vue": "^10.0.0",
79
+ "eslint-plugin-vue": "^10.1.0",
80
80
  "neostandard": "^0.12.1",
81
81
  "prettier": "^3.5.3"
82
82
  },
@@ -85,8 +85,8 @@
85
85
  "@commitlint/config-conventional": "^19.8.0",
86
86
  "@semantic-release/changelog": "^6.0.3",
87
87
  "@semantic-release/git": "^10.0.1",
88
- "@types/node": "^22.15.2",
89
- "eslint": "^9.25.1",
88
+ "@types/node": "^22.15.3",
89
+ "eslint": "^9.26.0",
90
90
  "husky": "^9.1.7",
91
91
  "lint-staged": "^15.5.1",
92
92
  "pkgroll": "^2.12.2",