@planfredapp/eslint-config 1.2.15 → 1.3.1
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 +45 -21
- package/base.js +6 -7
- package/cypress.js +10 -0
- package/package.json +8 -8
- package/vue.js +5 -0
package/README.md
CHANGED
|
@@ -32,14 +32,16 @@ npm install --save-dev eslint @planfredapp/eslint-config
|
|
|
32
32
|
| Cypress | `@planfredapp/eslint-config/cypress` | Base config, `typescript-eslint` recommended rules, Cypress globals, `.only()` protection |
|
|
33
33
|
| Test | `@planfredapp/eslint-config/test` | Base config, Vitest recommended rules, test globals, `.only()` protection |
|
|
34
34
|
|
|
35
|
-
Every specialized entrypoint already includes the complete base config. Use the base entrypoint by itself for plain JavaScript, or select a specialized entrypoint when it applies to the whole project.
|
|
35
|
+
Every specialized entrypoint already includes the complete base config and adds its own rules on top without loosening base's options. Cypress swaps the core unused-code rules for typescript-eslint's versions with the same options; in `.ts` files, typescript-eslint also switches off the core rules that the TypeScript compiler covers, such as `no-undef`, so those checks depend on running `tsc` over the files (unreachable code is only a compiler error with `allowUnreachableCode: false`). Use the base entrypoint by itself for plain JavaScript, or select a specialized entrypoint when it applies to the whole project.
|
|
36
|
+
|
|
37
|
+
All entrypoints lint `.js`, `.mjs`, and `.cjs` files (`.cjs` is parsed as CommonJS). The Vue entrypoint adds `.vue` files. Only the Cypress entrypoint parses TypeScript; it uses the TypeScript parser for every file, so it doesn't reject TypeScript syntax in `.js` files or ESM syntax in `.cjs` files.
|
|
36
38
|
|
|
37
39
|
### Vue-Specific Assumptions
|
|
38
40
|
|
|
39
41
|
The Vue config contains a few project-structure assumptions:
|
|
40
42
|
|
|
41
43
|
- `src/**/*` must use `@` imports instead of relative imports
|
|
42
|
-
- `src/components/**/*` enforces component/file-name matching
|
|
44
|
+
- `src/components/**/*` enforces component/file-name matching and a `name` property on Options API components
|
|
43
45
|
- The config is intended for Vue 3 single-file components
|
|
44
46
|
|
|
45
47
|
## Usage
|
|
@@ -109,40 +111,62 @@ export default [
|
|
|
109
111
|
]
|
|
110
112
|
```
|
|
111
113
|
|
|
112
|
-
If one root `eslint.config.js` combines multiple specialized configs, apply the base config once and scope only each specialized config's additional entries
|
|
114
|
+
If one root `eslint.config.js` combines multiple specialized configs, apply the base config once and scope only each specialized config's additional entries with `defineConfig`'s `extends`:
|
|
113
115
|
|
|
114
116
|
```js
|
|
115
117
|
import baseConfig from '@planfredapp/eslint-config'
|
|
116
118
|
import cypressConfig from '@planfredapp/eslint-config/cypress'
|
|
117
119
|
import testConfig from '@planfredapp/eslint-config/test'
|
|
120
|
+
import vueConfig from '@planfredapp/eslint-config/vue'
|
|
121
|
+
import { defineConfig } from 'eslint/config'
|
|
118
122
|
|
|
119
123
|
const withoutBase = config => config.slice(baseConfig.length)
|
|
120
|
-
const scope = (config, files) => config.map(entry => ({
|
|
121
|
-
...entry,
|
|
122
|
-
files,
|
|
123
|
-
}))
|
|
124
124
|
|
|
125
|
-
export default [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
]
|
|
125
|
+
export default defineConfig([
|
|
126
|
+
baseConfig,
|
|
127
|
+
{
|
|
128
|
+
files: [ 'src/**/*.{js,vue}' ],
|
|
129
|
+
extends: [ withoutBase(vueConfig) ],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
files: [ 'cypress/**/*.{js,ts}' ],
|
|
133
|
+
extends: [ withoutBase(cypressConfig) ],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
files: [ 'test/**/*.js' ],
|
|
137
|
+
extends: [ withoutBase(testConfig) ],
|
|
138
|
+
},
|
|
139
|
+
])
|
|
130
140
|
```
|
|
131
141
|
|
|
132
|
-
This avoids applying the base entries more than once. The specialized entrypoints intentionally begin with the same base config entries.
|
|
142
|
+
This avoids applying the base entries more than once. The specialized entrypoints intentionally begin with the same base config entries. Widen the `files` patterns if those folders also hold `.mjs`, `.cjs`, or other file types.
|
|
143
|
+
|
|
144
|
+
Vue's path-scoped entries (`src/**` and `src/components/**`) are relative to the config's base path. For a Vue app in a subfolder, set `basePath` instead of prefixing `files`, or those entries silently match nothing: `{ basePath: 'apps/web', files: [ 'src/**/*.{js,vue}' ], extends: [ withoutBase(vueConfig) ] }`.
|
|
145
|
+
|
|
146
|
+
Don't scope entries by overwriting their `files` (`config.map(entry => ({ ...entry, files }))`). Some entries carry their own `files`, and overwriting them widens their scope: typescript-eslint's `.ts`-only overrides would switch off `no-undef` for Cypress `.js` files, and Vue's component-only rules would apply to every file. `extends` intersects the patterns instead.
|
|
133
147
|
|
|
134
148
|
## What The Base Config Enforces
|
|
135
149
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
139
|
-
- Trailing commas for multiline arrays, objects, imports, exports, and
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
150
|
+
Each item below is covered by a valid and an invalid example in [`test/configs.test.js`](test/configs.test.js).
|
|
151
|
+
|
|
152
|
+
- 2-space indentation, single quotes, no semicolons
|
|
153
|
+
- Trailing commas for multiline arrays, objects, imports, exports, function params, and call arguments; commas at the end of the line, never on a line of their own
|
|
154
|
+
- Spaces inside array brackets (`[ 1 ]`); arrays with 2+ items put each item on its own line
|
|
155
|
+
- Object literals with 2+ properties break after `{` and before `}`; inside, either all properties share one line or each gets its own line. Object destructuring may stay on one line; array destructuring follows the array rules
|
|
156
|
+
- A space before function parentheses (`function f ()`, `method ()`)
|
|
157
|
+
- A blank line between statements, including before `return`. Consecutive imports, consecutive `const`/`let`/`var` declarations, and consecutive expression statements may be adjacent; exported and function declarations are always separated
|
|
158
|
+
- Chains of 2+ calls put each call on its own line (`list.map(f).join()` → one call per line); a single call stays inline
|
|
159
|
+
- Imports in groups separated by a blank line: Node builtins and packages together, then relative paths, each group alphabetized. Without an import resolver, aliases and subpath imports (`@/`, `#`, `~/`) form a last group after relative paths; an `import-x/internal-regex` setting that marks them internal moves them between packages and relative paths
|
|
160
|
+
- `no-var`, `prefer-const`, `eqeqeq` (except `== null`), and a broad set of core correctness rules
|
|
161
|
+
- Unused function arguments, unused caught errors, and rest siblings used to omit properties are allowed; unused variables are not. An unused first parameter named `err` or `error` is reported, because `n/handle-callback-err` requires handling it
|
|
143
162
|
- Promise executor parameters named `resolve` and `reject`
|
|
144
163
|
|
|
145
|
-
The Vue
|
|
164
|
+
### What The Vue Config Adds
|
|
165
|
+
|
|
166
|
+
- `@/` imports inside `src/` through the bundled `no-relative-import-paths` rule, with an autofix for relative imports
|
|
167
|
+
- Template expressions follow their own style: no spaces inside array brackets, arrays may stay on one line (`:items="[1, 2]"`), and multi-property objects put each property on its own line
|
|
168
|
+
- A blank line between sibling template elements
|
|
169
|
+
- Blocks ordered `<template>`, `<script>`, `<style>`, blank lines around multi-line component options, no `v-html`
|
|
146
170
|
|
|
147
171
|
## Package Contents
|
|
148
172
|
|
package/base.js
CHANGED
|
@@ -17,7 +17,6 @@ export default [
|
|
|
17
17
|
stylistic: stylisticPlugin,
|
|
18
18
|
},
|
|
19
19
|
languageOptions: {
|
|
20
|
-
sourceType: 'module',
|
|
21
20
|
globals: {
|
|
22
21
|
...globals.node,
|
|
23
22
|
...globals.browser,
|
|
@@ -55,10 +54,6 @@ export default [
|
|
|
55
54
|
ignoreGlobals: true,
|
|
56
55
|
},
|
|
57
56
|
],
|
|
58
|
-
'comma-style': [
|
|
59
|
-
'error',
|
|
60
|
-
'last',
|
|
61
|
-
],
|
|
62
57
|
'constructor-super': 'error',
|
|
63
58
|
curly: [
|
|
64
59
|
'error',
|
|
@@ -136,10 +131,10 @@ export default [
|
|
|
136
131
|
'no-useless-catch': 'error',
|
|
137
132
|
'no-new': 'error',
|
|
138
133
|
'no-new-func': 'error',
|
|
139
|
-
'no-new-
|
|
140
|
-
'no-new-symbol': 'error',
|
|
134
|
+
'no-new-native-nonconstructor': 'error',
|
|
141
135
|
'no-new-wrappers': 'error',
|
|
142
136
|
'no-obj-calls': 'error',
|
|
137
|
+
'no-object-constructor': 'error',
|
|
143
138
|
'no-octal': 'error',
|
|
144
139
|
'no-octal-escape': 'error',
|
|
145
140
|
'no-proto': 'error',
|
|
@@ -352,6 +347,10 @@ export default [
|
|
|
352
347
|
after: true,
|
|
353
348
|
},
|
|
354
349
|
],
|
|
350
|
+
'stylistic/comma-style': [
|
|
351
|
+
'error',
|
|
352
|
+
'last',
|
|
353
|
+
],
|
|
355
354
|
'stylistic/computed-property-spacing': [
|
|
356
355
|
'error',
|
|
357
356
|
'never',
|
package/cypress.js
CHANGED
|
@@ -6,9 +6,17 @@ import tsEslint from 'typescript-eslint'
|
|
|
6
6
|
|
|
7
7
|
import baseConfig from './base.js'
|
|
8
8
|
|
|
9
|
+
// typescript-eslint replaces these core rules with its own versions, so carry over the base options
|
|
10
|
+
const baseRule = name => baseConfig.findLast(config => !config.files && config.rules?.[name]).rules[name]
|
|
11
|
+
|
|
9
12
|
export default [
|
|
10
13
|
...baseConfig,
|
|
11
14
|
...tsEslint.configs.recommended,
|
|
15
|
+
{
|
|
16
|
+
// typescript-eslint sets sourceType: 'module' for every file; restore ESLint's default for .cjs
|
|
17
|
+
files: [ '**/*.cjs' ],
|
|
18
|
+
languageOptions: { sourceType: 'commonjs' },
|
|
19
|
+
},
|
|
12
20
|
cypressPlugin.configs.recommended,
|
|
13
21
|
{
|
|
14
22
|
plugins: {
|
|
@@ -23,6 +31,8 @@ export default [
|
|
|
23
31
|
},
|
|
24
32
|
},
|
|
25
33
|
rules: {
|
|
34
|
+
'@typescript-eslint/no-unused-expressions': baseRule('no-unused-expressions'),
|
|
35
|
+
'@typescript-eslint/no-unused-vars': baseRule('no-unused-vars'),
|
|
26
36
|
'@typescript-eslint/no-require-imports': 'off',
|
|
27
37
|
'noOnlyTestsPlugin/no-only-tests': 'error',
|
|
28
38
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planfredapp/eslint-config",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Shared ESLint 10 flat configurations for Planfred projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -44,20 +44,20 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@eslint/js": "10.0.1",
|
|
46
46
|
"@stylistic/eslint-plugin": "5.10.0",
|
|
47
|
-
"@vitest/eslint-plugin": "1.6.
|
|
47
|
+
"@vitest/eslint-plugin": "1.6.28",
|
|
48
48
|
"eslint-plugin-cypress": "7.0.2",
|
|
49
49
|
"eslint-plugin-import-x": "4.17.1",
|
|
50
|
-
"eslint-plugin-n": "18.
|
|
50
|
+
"eslint-plugin-n": "18.5.0",
|
|
51
51
|
"eslint-plugin-no-only-tests": "3.4.0",
|
|
52
|
-
"eslint-plugin-vue": "10.11.
|
|
53
|
-
"globals": "17.
|
|
54
|
-
"typescript-eslint": "8.
|
|
52
|
+
"eslint-plugin-vue": "10.11.1",
|
|
53
|
+
"globals": "17.13.0",
|
|
54
|
+
"typescript-eslint": "8.72.0",
|
|
55
55
|
"vue-eslint-parser": "10.4.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"eslint": "10.
|
|
58
|
+
"eslint": "10.13.0",
|
|
59
59
|
"typescript": "6.0.3",
|
|
60
|
-
"vitest": "5.0.
|
|
60
|
+
"vitest": "5.0.5"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"eslint": ">=10.0.0"
|
package/vue.js
CHANGED
|
@@ -7,6 +7,11 @@ import noRelativeImportPathsPlugin from './no-relative-import-paths.js'
|
|
|
7
7
|
export default [
|
|
8
8
|
...baseConfig,
|
|
9
9
|
...vuePlugin.configs['flat/recommended'],
|
|
10
|
+
{
|
|
11
|
+
// eslint-plugin-vue sets sourceType: 'module' for every file; restore ESLint's default for .cjs
|
|
12
|
+
files: [ '**/*.cjs' ],
|
|
13
|
+
languageOptions: { sourceType: 'commonjs' },
|
|
14
|
+
},
|
|
10
15
|
{
|
|
11
16
|
plugins: {
|
|
12
17
|
vue: vuePlugin,
|