@planfredapp/eslint-config 1.0.9
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 +111 -0
- package/base.js +457 -0
- package/cypress.js +30 -0
- package/eslint.config.js +9 -0
- package/package.json +55 -0
- package/test.js +45 -0
- package/vitest.config.js +8 -0
- package/vue.js +191 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# planfred-eslint-config
|
|
2
|
+
|
|
3
|
+
Shared ESLint configurations for the Planfred monorepo.
|
|
4
|
+
|
|
5
|
+
## Available Configurations
|
|
6
|
+
|
|
7
|
+
### Base Configuration
|
|
8
|
+
|
|
9
|
+
The base configuration includes common rules and plugins used across all projects:
|
|
10
|
+
|
|
11
|
+
- Standard JavaScript rules
|
|
12
|
+
- Import/export rules
|
|
13
|
+
- Node.js specific rules
|
|
14
|
+
- Promise handling rules
|
|
15
|
+
- Stylistic rules
|
|
16
|
+
|
|
17
|
+
### Vue Configuration
|
|
18
|
+
|
|
19
|
+
Extends the base configuration with Vue.js specific rules:
|
|
20
|
+
|
|
21
|
+
- Vue component rules
|
|
22
|
+
- Template-specific styling rules
|
|
23
|
+
- Component naming conventions
|
|
24
|
+
- Vue-specific import path rules
|
|
25
|
+
|
|
26
|
+
### Cypress Configuration
|
|
27
|
+
|
|
28
|
+
Extends the base configuration with Cypress testing rules:
|
|
29
|
+
|
|
30
|
+
- TypeScript support
|
|
31
|
+
- Cypress-specific globals and rules
|
|
32
|
+
- Test-specific linting rules
|
|
33
|
+
|
|
34
|
+
### Test Configuration
|
|
35
|
+
|
|
36
|
+
Extends the base configuration with testing framework rules:
|
|
37
|
+
|
|
38
|
+
- Vitest support
|
|
39
|
+
- Test-specific globals
|
|
40
|
+
- Testing best practices
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### In ESLint Config Files
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// For base configuration
|
|
48
|
+
import baseConfig from '@planfred/eslint-config/base'
|
|
49
|
+
|
|
50
|
+
export default [
|
|
51
|
+
...baseConfig,
|
|
52
|
+
// your specific overrides
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
// For Vue projects
|
|
56
|
+
import vueConfig from '@planfred/eslint-config/vue'
|
|
57
|
+
|
|
58
|
+
export default [
|
|
59
|
+
...vueConfig,
|
|
60
|
+
// your specific overrides
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
// For Cypress tests
|
|
64
|
+
import cypressConfig from '@planfred/eslint-config/cypress'
|
|
65
|
+
|
|
66
|
+
export default [
|
|
67
|
+
...cypressConfig,
|
|
68
|
+
// your specific overrides
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
// For test files
|
|
72
|
+
import testConfig from '@planfred/eslint-config/test'
|
|
73
|
+
|
|
74
|
+
export default [
|
|
75
|
+
...testConfig,
|
|
76
|
+
// your specific overrides
|
|
77
|
+
]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Package.json Dependencies
|
|
81
|
+
|
|
82
|
+
Add the shared config as a dependency in your package.json using the GitHub repository URL:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"dependencies": {
|
|
87
|
+
"@planfred/eslint-config": "git+https://github.com/planfred/eslint-config.git"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Alternatively, you can use a specific version or branch:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"@planfred/eslint-config": "git+https://github.com/planfred/eslint-config.git#v1.0.0"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Configuration Structure
|
|
103
|
+
|
|
104
|
+
The shared configurations are organized as follows:
|
|
105
|
+
|
|
106
|
+
- `base.js` - Core configuration with common rules
|
|
107
|
+
- `vue.js` - Vue.js specific configuration extending base
|
|
108
|
+
- `cypress.js` - Cypress testing configuration extending base
|
|
109
|
+
- `test.js` - General testing configuration extending base
|
|
110
|
+
|
|
111
|
+
Each configuration can be extended and overridden as needed in individual projects.
|
package/base.js
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
2
|
+
import js from '@eslint/js'
|
|
3
|
+
import stylisticPlugin from '@stylistic/eslint-plugin'
|
|
4
|
+
import importPlugin from 'eslint-plugin-import'
|
|
5
|
+
import nodePlugin from 'eslint-plugin-n'
|
|
6
|
+
import promisePlugin from 'eslint-plugin-promise'
|
|
7
|
+
import globals from 'globals'
|
|
8
|
+
|
|
9
|
+
export default [
|
|
10
|
+
js.configs.recommended,
|
|
11
|
+
{
|
|
12
|
+
plugins: {
|
|
13
|
+
import: importPlugin,
|
|
14
|
+
promise: promisePlugin,
|
|
15
|
+
n: nodePlugin,
|
|
16
|
+
stylistic: stylisticPlugin,
|
|
17
|
+
},
|
|
18
|
+
languageOptions: {
|
|
19
|
+
sourceType: 'module',
|
|
20
|
+
globals: {
|
|
21
|
+
...globals.node,
|
|
22
|
+
...globals.browser,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
rules: {
|
|
26
|
+
'comma-dangle': 'off', // turn off because of stylistic/comma-dangle
|
|
27
|
+
'no-console': 'off',
|
|
28
|
+
|
|
29
|
+
// standard rules
|
|
30
|
+
'no-var': 'warn',
|
|
31
|
+
'object-shorthand': ['warn', 'properties'],
|
|
32
|
+
'accessor-pairs': [
|
|
33
|
+
'error',
|
|
34
|
+
{
|
|
35
|
+
setWithoutGet: true,
|
|
36
|
+
enforceForClassMembers: true,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
'array-callback-return': [
|
|
40
|
+
'error',
|
|
41
|
+
{
|
|
42
|
+
allowImplicit: false,
|
|
43
|
+
checkForEach: false,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
camelcase: [
|
|
47
|
+
'error',
|
|
48
|
+
{
|
|
49
|
+
allow: ['^UNSAFE_'],
|
|
50
|
+
properties: 'never',
|
|
51
|
+
ignoreGlobals: true,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
'comma-style': ['error', 'last'],
|
|
55
|
+
'constructor-super': 'error',
|
|
56
|
+
curly: ['error', 'multi-line'],
|
|
57
|
+
'default-case-last': 'error',
|
|
58
|
+
'dot-notation': ['error', { allowKeywords: true }],
|
|
59
|
+
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
|
60
|
+
'new-cap': [
|
|
61
|
+
'error',
|
|
62
|
+
{
|
|
63
|
+
newIsCap: true,
|
|
64
|
+
capIsNew: false,
|
|
65
|
+
properties: true,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
'no-array-constructor': 'error',
|
|
69
|
+
'no-async-promise-executor': 'error',
|
|
70
|
+
'no-caller': 'error',
|
|
71
|
+
'no-case-declarations': 'error',
|
|
72
|
+
'no-class-assign': 'error',
|
|
73
|
+
'no-compare-neg-zero': 'error',
|
|
74
|
+
'no-cond-assign': 'error',
|
|
75
|
+
'no-const-assign': 'error',
|
|
76
|
+
'no-constant-condition': ['error', { checkLoops: false }],
|
|
77
|
+
'no-control-regex': 'error',
|
|
78
|
+
'no-debugger': 'error',
|
|
79
|
+
'no-delete-var': 'error',
|
|
80
|
+
'no-dupe-args': 'error',
|
|
81
|
+
'no-dupe-class-members': 'error',
|
|
82
|
+
'no-dupe-keys': 'error',
|
|
83
|
+
'no-duplicate-case': 'error',
|
|
84
|
+
'no-useless-backreference': 'error',
|
|
85
|
+
'no-empty': ['error', { allowEmptyCatch: true }],
|
|
86
|
+
'no-empty-character-class': 'error',
|
|
87
|
+
'no-empty-pattern': 'error',
|
|
88
|
+
'no-eval': 'error',
|
|
89
|
+
'no-ex-assign': 'error',
|
|
90
|
+
'no-extend-native': 'error',
|
|
91
|
+
'no-extra-bind': 'error',
|
|
92
|
+
'no-extra-boolean-cast': 'error',
|
|
93
|
+
'no-fallthrough': 'error',
|
|
94
|
+
'no-func-assign': 'error',
|
|
95
|
+
'no-global-assign': 'error',
|
|
96
|
+
'no-implied-eval': 'error',
|
|
97
|
+
'no-import-assign': 'error',
|
|
98
|
+
'no-invalid-regexp': 'error',
|
|
99
|
+
'no-irregular-whitespace': 'error',
|
|
100
|
+
'no-iterator': 'error',
|
|
101
|
+
'no-labels': [
|
|
102
|
+
'error',
|
|
103
|
+
{
|
|
104
|
+
allowLoop: false,
|
|
105
|
+
allowSwitch: false,
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
'no-lone-blocks': 'error',
|
|
109
|
+
'no-loss-of-precision': 'error',
|
|
110
|
+
'no-misleading-character-class': 'error',
|
|
111
|
+
'no-multi-str': 'error',
|
|
112
|
+
'no-prototype-builtins': 'error',
|
|
113
|
+
'no-useless-catch': 'error',
|
|
114
|
+
'no-new': 'error',
|
|
115
|
+
'no-new-func': 'error',
|
|
116
|
+
'no-new-object': 'error',
|
|
117
|
+
'no-new-symbol': 'error',
|
|
118
|
+
'no-new-wrappers': 'error',
|
|
119
|
+
'no-obj-calls': 'error',
|
|
120
|
+
'no-octal': 'error',
|
|
121
|
+
'no-octal-escape': 'error',
|
|
122
|
+
'no-proto': 'error',
|
|
123
|
+
'no-redeclare': ['error', { builtinGlobals: false }],
|
|
124
|
+
'no-regex-spaces': 'error',
|
|
125
|
+
'no-return-assign': ['error', 'except-parens'],
|
|
126
|
+
'no-self-assign': ['error', { props: true }],
|
|
127
|
+
'no-self-compare': 'error',
|
|
128
|
+
'no-sequences': 'error',
|
|
129
|
+
'no-shadow-restricted-names': 'error',
|
|
130
|
+
'no-sparse-arrays': 'error',
|
|
131
|
+
'no-template-curly-in-string': 'error',
|
|
132
|
+
'no-this-before-super': 'error',
|
|
133
|
+
'no-throw-literal': 'error',
|
|
134
|
+
'no-undef': 'error',
|
|
135
|
+
'no-undef-init': 'error',
|
|
136
|
+
'no-unexpected-multiline': 'error',
|
|
137
|
+
'no-unmodified-loop-condition': 'error',
|
|
138
|
+
'no-unneeded-ternary': ['error', { defaultAssignment: false }],
|
|
139
|
+
'no-unreachable': 'error',
|
|
140
|
+
'no-unreachable-loop': 'error',
|
|
141
|
+
'no-unsafe-finally': 'error',
|
|
142
|
+
'no-unsafe-negation': 'error',
|
|
143
|
+
'no-unused-expressions': [
|
|
144
|
+
'error',
|
|
145
|
+
{
|
|
146
|
+
allowShortCircuit: true,
|
|
147
|
+
allowTernary: true,
|
|
148
|
+
allowTaggedTemplates: true,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
'no-unused-vars': [
|
|
152
|
+
'error',
|
|
153
|
+
{
|
|
154
|
+
args: 'none',
|
|
155
|
+
caughtErrors: 'none',
|
|
156
|
+
ignoreRestSiblings: true,
|
|
157
|
+
vars: 'all',
|
|
158
|
+
argsIgnorePattern: '^_',
|
|
159
|
+
destructuredArrayIgnorePattern: '^_',
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
'no-use-before-define': [
|
|
163
|
+
'error',
|
|
164
|
+
{
|
|
165
|
+
functions: false,
|
|
166
|
+
classes: false,
|
|
167
|
+
variables: false,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
'no-useless-call': 'error',
|
|
171
|
+
'no-useless-computed-key': 'error',
|
|
172
|
+
'no-useless-constructor': 'error',
|
|
173
|
+
'no-useless-escape': 'error',
|
|
174
|
+
'no-useless-rename': 'error',
|
|
175
|
+
'no-useless-return': 'error',
|
|
176
|
+
'no-void': 'error',
|
|
177
|
+
'no-with': 'error',
|
|
178
|
+
'one-var': ['error', { initialized: 'never' }],
|
|
179
|
+
'prefer-const': ['error', { destructuring: 'all' }],
|
|
180
|
+
'prefer-promise-reject-errors': 'error',
|
|
181
|
+
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
|
|
182
|
+
'symbol-description': 'error',
|
|
183
|
+
'unicode-bom': ['error', 'never'],
|
|
184
|
+
'use-isnan': [
|
|
185
|
+
'error',
|
|
186
|
+
{
|
|
187
|
+
enforceForSwitchCase: true,
|
|
188
|
+
enforceForIndexOf: true,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
'valid-typeof': ['error', { requireStringLiterals: true }],
|
|
192
|
+
yoda: ['error', 'never'],
|
|
193
|
+
|
|
194
|
+
// import rules
|
|
195
|
+
'import/export': 'error',
|
|
196
|
+
'import/first': 'error',
|
|
197
|
+
'import/order': [
|
|
198
|
+
'error',
|
|
199
|
+
{
|
|
200
|
+
'newlines-between': 'always',
|
|
201
|
+
groups: [
|
|
202
|
+
['builtin', 'external'],
|
|
203
|
+
'internal',
|
|
204
|
+
['parent', 'sibling', 'index'],
|
|
205
|
+
],
|
|
206
|
+
alphabetize: {
|
|
207
|
+
order: 'asc',
|
|
208
|
+
caseInsensitive: true,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
'import/no-absolute-path': [
|
|
213
|
+
'error',
|
|
214
|
+
{
|
|
215
|
+
esmodule: true,
|
|
216
|
+
commonjs: true,
|
|
217
|
+
amd: false,
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
'import/no-duplicates': 'error',
|
|
221
|
+
'import/no-named-default': 'error',
|
|
222
|
+
'import/no-webpack-loader-syntax': 'error',
|
|
223
|
+
|
|
224
|
+
// n rules
|
|
225
|
+
'n/handle-callback-err': ['error', '^(err|error)$'],
|
|
226
|
+
'n/no-callback-literal': 'error',
|
|
227
|
+
'n/no-deprecated-api': 'error',
|
|
228
|
+
'n/no-exports-assign': 'error',
|
|
229
|
+
'n/no-new-require': 'error',
|
|
230
|
+
'n/no-path-concat': 'error',
|
|
231
|
+
'n/process-exit-as-throw': 'error',
|
|
232
|
+
|
|
233
|
+
// promise rules
|
|
234
|
+
'promise/param-names': 'error',
|
|
235
|
+
|
|
236
|
+
// custom style rules
|
|
237
|
+
'stylistic/array-bracket-newline': ['warn', 'consistent'],
|
|
238
|
+
'stylistic/array-element-newline': [
|
|
239
|
+
'warn',
|
|
240
|
+
{ ArrayExpression: 'consistent' },
|
|
241
|
+
],
|
|
242
|
+
'stylistic/arrow-parens': 'off',
|
|
243
|
+
'stylistic/template-curly-spacing': ['off'],
|
|
244
|
+
|
|
245
|
+
// standard style rules
|
|
246
|
+
'stylistic/array-bracket-spacing': ['error', 'never'],
|
|
247
|
+
'stylistic/arrow-spacing': [
|
|
248
|
+
'error',
|
|
249
|
+
{
|
|
250
|
+
before: true,
|
|
251
|
+
after: true,
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
'stylistic/block-spacing': ['error', 'always'],
|
|
255
|
+
'stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
|
256
|
+
'stylistic/comma-dangle': [
|
|
257
|
+
'error',
|
|
258
|
+
{
|
|
259
|
+
arrays: 'always-multiline',
|
|
260
|
+
objects: 'always-multiline',
|
|
261
|
+
imports: 'always-multiline',
|
|
262
|
+
exports: 'always-multiline',
|
|
263
|
+
functions: 'always-multiline',
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
'stylistic/comma-spacing': [
|
|
267
|
+
'error',
|
|
268
|
+
{
|
|
269
|
+
before: false,
|
|
270
|
+
after: true,
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
'stylistic/computed-property-spacing': [
|
|
274
|
+
'error',
|
|
275
|
+
'never',
|
|
276
|
+
{ enforceForClassMembers: true },
|
|
277
|
+
],
|
|
278
|
+
'stylistic/dot-location': ['error', 'property'],
|
|
279
|
+
'stylistic/eol-last': 'error',
|
|
280
|
+
'stylistic/function-call-spacing': ['error', 'never'],
|
|
281
|
+
'stylistic/generator-star-spacing': [
|
|
282
|
+
'error',
|
|
283
|
+
{
|
|
284
|
+
before: true,
|
|
285
|
+
after: true,
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
'stylistic/indent': [
|
|
289
|
+
'error',
|
|
290
|
+
2,
|
|
291
|
+
{
|
|
292
|
+
SwitchCase: 1,
|
|
293
|
+
VariableDeclarator: 1,
|
|
294
|
+
outerIIFEBody: 1,
|
|
295
|
+
MemberExpression: 1,
|
|
296
|
+
FunctionDeclaration: {
|
|
297
|
+
parameters: 1,
|
|
298
|
+
body: 1,
|
|
299
|
+
},
|
|
300
|
+
FunctionExpression: {
|
|
301
|
+
parameters: 1,
|
|
302
|
+
body: 1,
|
|
303
|
+
},
|
|
304
|
+
CallExpression: { arguments: 1 },
|
|
305
|
+
ArrayExpression: 1,
|
|
306
|
+
ObjectExpression: 1,
|
|
307
|
+
ImportDeclaration: 1,
|
|
308
|
+
flatTernaryExpressions: false,
|
|
309
|
+
ignoreComments: false,
|
|
310
|
+
ignoredNodes: [
|
|
311
|
+
'TemplateLiteral *',
|
|
312
|
+
'JSXElement',
|
|
313
|
+
'JSXElement > *',
|
|
314
|
+
'JSXAttribute',
|
|
315
|
+
'JSXIdentifier',
|
|
316
|
+
'JSXNamespacedName',
|
|
317
|
+
'JSXMemberExpression',
|
|
318
|
+
'JSXSpreadAttribute',
|
|
319
|
+
'JSXExpressionContainer',
|
|
320
|
+
'JSXOpeningElement',
|
|
321
|
+
'JSXClosingElement',
|
|
322
|
+
'JSXFragment',
|
|
323
|
+
'JSXOpeningFragment',
|
|
324
|
+
'JSXClosingFragment',
|
|
325
|
+
'JSXText',
|
|
326
|
+
'JSXEmptyExpression',
|
|
327
|
+
'JSXSpreadChild',
|
|
328
|
+
],
|
|
329
|
+
offsetTernaryExpressions: true,
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
'stylistic/key-spacing': [
|
|
333
|
+
'error',
|
|
334
|
+
{
|
|
335
|
+
beforeColon: false,
|
|
336
|
+
afterColon: true,
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
'stylistic/keyword-spacing': [
|
|
340
|
+
'error',
|
|
341
|
+
{
|
|
342
|
+
before: true,
|
|
343
|
+
after: true,
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
'stylistic/lines-between-class-members': [
|
|
347
|
+
'error',
|
|
348
|
+
'always',
|
|
349
|
+
{ exceptAfterSingleLine: true },
|
|
350
|
+
],
|
|
351
|
+
'stylistic/multiline-ternary': ['error', 'always-multiline'],
|
|
352
|
+
'stylistic/new-parens': 'error',
|
|
353
|
+
'stylistic/no-extra-parens': ['error', 'functions'],
|
|
354
|
+
'stylistic/no-floating-decimal': 'error',
|
|
355
|
+
'stylistic/no-mixed-operators': [
|
|
356
|
+
'error',
|
|
357
|
+
{
|
|
358
|
+
groups: [
|
|
359
|
+
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
|
|
360
|
+
['&&', '||'],
|
|
361
|
+
['in', 'instanceof'],
|
|
362
|
+
],
|
|
363
|
+
allowSamePrecedence: true,
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
'stylistic/no-mixed-spaces-and-tabs': 'error',
|
|
367
|
+
'stylistic/no-multi-spaces': 'error',
|
|
368
|
+
'stylistic/no-multiple-empty-lines': [
|
|
369
|
+
'error',
|
|
370
|
+
{
|
|
371
|
+
max: 1,
|
|
372
|
+
maxBOF: 0,
|
|
373
|
+
maxEOF: 0,
|
|
374
|
+
},
|
|
375
|
+
],
|
|
376
|
+
'stylistic/no-tabs': 'error',
|
|
377
|
+
'stylistic/no-trailing-spaces': 'error',
|
|
378
|
+
'stylistic/no-whitespace-before-property': 'error',
|
|
379
|
+
'stylistic/object-curly-newline': [
|
|
380
|
+
'error',
|
|
381
|
+
{
|
|
382
|
+
multiline: true,
|
|
383
|
+
consistent: true,
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
'stylistic/object-curly-spacing': ['error', 'always'],
|
|
387
|
+
'stylistic/object-property-newline': 'error',
|
|
388
|
+
'stylistic/operator-linebreak': [
|
|
389
|
+
'error',
|
|
390
|
+
'after',
|
|
391
|
+
{
|
|
392
|
+
overrides: {
|
|
393
|
+
'?': 'before',
|
|
394
|
+
':': 'before',
|
|
395
|
+
'|>': 'before',
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
],
|
|
399
|
+
'stylistic/padded-blocks': [
|
|
400
|
+
'error',
|
|
401
|
+
{
|
|
402
|
+
blocks: 'never',
|
|
403
|
+
switches: 'never',
|
|
404
|
+
classes: 'never',
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
'stylistic/quote-props': ['error', 'as-needed'],
|
|
408
|
+
'stylistic/quotes': [
|
|
409
|
+
'error',
|
|
410
|
+
'single',
|
|
411
|
+
{
|
|
412
|
+
avoidEscape: true,
|
|
413
|
+
allowTemplateLiterals: 'never',
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
'stylistic/rest-spread-spacing': ['error', 'never'],
|
|
417
|
+
'stylistic/semi': ['error', 'never'],
|
|
418
|
+
'stylistic/semi-spacing': [
|
|
419
|
+
'error',
|
|
420
|
+
{
|
|
421
|
+
before: false,
|
|
422
|
+
after: true,
|
|
423
|
+
},
|
|
424
|
+
],
|
|
425
|
+
'stylistic/space-before-blocks': ['error', 'always'],
|
|
426
|
+
'stylistic/space-before-function-paren': ['error', 'always'],
|
|
427
|
+
'stylistic/space-in-parens': ['error', 'never'],
|
|
428
|
+
'stylistic/space-infix-ops': 'error',
|
|
429
|
+
'stylistic/space-unary-ops': [
|
|
430
|
+
'error',
|
|
431
|
+
{
|
|
432
|
+
words: true,
|
|
433
|
+
nonwords: false,
|
|
434
|
+
},
|
|
435
|
+
],
|
|
436
|
+
'stylistic/spaced-comment': [
|
|
437
|
+
'error',
|
|
438
|
+
'always',
|
|
439
|
+
{
|
|
440
|
+
line: { markers: ['*package', '!', '/', ',', '='] },
|
|
441
|
+
block: {
|
|
442
|
+
balanced: true,
|
|
443
|
+
markers: ['*package', '!', ',', ':', '::', 'flow-include'],
|
|
444
|
+
exceptions: ['*'],
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
],
|
|
448
|
+
'stylistic/template-tag-spacing': ['error', 'never'],
|
|
449
|
+
'stylistic/wrap-iife': [
|
|
450
|
+
'error',
|
|
451
|
+
'any',
|
|
452
|
+
{ functionPrototypeMethods: true },
|
|
453
|
+
],
|
|
454
|
+
'stylistic/yield-star-spacing': ['error', 'both'],
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
]
|
package/cypress.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
2
|
+
import cypressPlugin from 'eslint-plugin-cypress/flat'
|
|
3
|
+
import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'
|
|
4
|
+
import globals from 'globals'
|
|
5
|
+
import tsEslint from 'typescript-eslint'
|
|
6
|
+
|
|
7
|
+
import baseConfig from './base.js'
|
|
8
|
+
|
|
9
|
+
export default [
|
|
10
|
+
...baseConfig,
|
|
11
|
+
...tsEslint.configs.recommended,
|
|
12
|
+
cypressPlugin.configs.recommended,
|
|
13
|
+
{
|
|
14
|
+
plugins: {
|
|
15
|
+
'@typescript-eslint': tsEslint.plugin,
|
|
16
|
+
noOnlyTestsPlugin,
|
|
17
|
+
},
|
|
18
|
+
languageOptions: {
|
|
19
|
+
parser: tsEslint.parser,
|
|
20
|
+
globals: {
|
|
21
|
+
...globals.node,
|
|
22
|
+
...globals.browser,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
rules: {
|
|
26
|
+
'@typescript-eslint/no-require-imports': 'off',
|
|
27
|
+
'noOnlyTestsPlugin/no-only-tests': 'error',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
]
|
package/eslint.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@planfredapp/eslint-config",
|
|
3
|
+
"version": "1.0.9",
|
|
4
|
+
"description": "Shared ESLint configurations for Planfred monorepo",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./base.js",
|
|
9
|
+
"./base": "./base.js",
|
|
10
|
+
"./vue": "./vue.js",
|
|
11
|
+
"./cypress": "./cypress.js",
|
|
12
|
+
"./test": "./test.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"*.js"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"lint:fix": "eslint . --fix",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"test:run": "vitest run",
|
|
22
|
+
"ncu": "NCU_COOLDOWN_DAYS=${NCU_COOLDOWN_DAYS:-3}; npx npm-check-updates@latest -u --cooldown $NCU_COOLDOWN_DAYS",
|
|
23
|
+
"upgrade": "git stash; NCU_OUTPUT=${node --run ncu}; npm install; echo \"$NCU_OUTPUT\"; git commit -am \"Upgrade npm packages: \n\n$NCU_OUTPUT\"; git push --force-with-lease;",
|
|
24
|
+
"tag": "git tag v$(node -p \"require('./package.json').version\") || true",
|
|
25
|
+
"tag:push": "git push origin v$(node -p \"require('./package.json').version\")",
|
|
26
|
+
"release": "npm run tag && npm run tag:push",
|
|
27
|
+
"version:patch": "npm version patch && npm run release",
|
|
28
|
+
"version:minor": "npm version minor && npm run release",
|
|
29
|
+
"version:major": "npm version major && npm run release",
|
|
30
|
+
"publish": "npm publish --access public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@eslint/js": "9.36.0",
|
|
34
|
+
"@stylistic/eslint-plugin": "5.4.0",
|
|
35
|
+
"eslint-plugin-import": "2.32.0",
|
|
36
|
+
"eslint-plugin-n": "17.23.1",
|
|
37
|
+
"eslint-plugin-promise": "7.2.1",
|
|
38
|
+
"eslint-plugin-vue": "10.5.0",
|
|
39
|
+
"eslint-plugin-cypress": "5.1.1",
|
|
40
|
+
"eslint-plugin-no-only-tests": "3.3.0",
|
|
41
|
+
"eslint-plugin-no-relative-import-paths": "1.6.1",
|
|
42
|
+
"@vitest/eslint-plugin": "1.3.13",
|
|
43
|
+
"typescript-eslint": "8.44.0",
|
|
44
|
+
"globals": "16.4.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"vitest": "3.2.4",
|
|
48
|
+
"eslint": "9.36.0",
|
|
49
|
+
"typescript": "5.9.2",
|
|
50
|
+
"vue-eslint-parser": "10.2.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"eslint": "9.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
2
|
+
import vitestPlugin from '@vitest/eslint-plugin'
|
|
3
|
+
import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests'
|
|
4
|
+
import globals from 'globals'
|
|
5
|
+
|
|
6
|
+
import baseConfig from './base.js'
|
|
7
|
+
|
|
8
|
+
export default [
|
|
9
|
+
...baseConfig,
|
|
10
|
+
{
|
|
11
|
+
plugins: {
|
|
12
|
+
noOnlyTestsPlugin,
|
|
13
|
+
vitest: vitestPlugin,
|
|
14
|
+
},
|
|
15
|
+
languageOptions: {
|
|
16
|
+
globals: {
|
|
17
|
+
...globals.node,
|
|
18
|
+
// Test globals
|
|
19
|
+
describe: 'readonly',
|
|
20
|
+
it: 'readonly',
|
|
21
|
+
test: 'readonly',
|
|
22
|
+
expect: 'readonly',
|
|
23
|
+
beforeEach: 'readonly',
|
|
24
|
+
beforeAll: 'readonly',
|
|
25
|
+
afterEach: 'readonly',
|
|
26
|
+
afterAll: 'readonly',
|
|
27
|
+
vi: 'readonly',
|
|
28
|
+
// Additional test globals
|
|
29
|
+
assert: 'readonly',
|
|
30
|
+
suite: 'readonly',
|
|
31
|
+
spec: 'readonly',
|
|
32
|
+
context: 'readonly',
|
|
33
|
+
// Chai globals
|
|
34
|
+
should: 'readonly',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
rules: {
|
|
38
|
+
...vitestPlugin.configs.recommended.rules,
|
|
39
|
+
'vitest/valid-expect': 'off', // Produces too much false positives right now. Try again at some point.
|
|
40
|
+
'vitest/expect-expect': 'off', // Sometimes expect statements are hidden in helper functions.
|
|
41
|
+
'vitest/no-commented-out-tests': 'off',
|
|
42
|
+
'noOnlyTestsPlugin/no-only-tests': 'error',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
]
|
package/vitest.config.js
ADDED
package/vue.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
2
|
+
import noRelativeImportPathsPlugin from 'eslint-plugin-no-relative-import-paths'
|
|
3
|
+
import vuePlugin from 'eslint-plugin-vue'
|
|
4
|
+
|
|
5
|
+
import baseConfig from './base.js'
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
...baseConfig,
|
|
9
|
+
...vuePlugin.configs['flat/recommended'],
|
|
10
|
+
{
|
|
11
|
+
plugins: {
|
|
12
|
+
vue: vuePlugin,
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
// vue rules
|
|
16
|
+
'vue/padding-lines-in-component-definition': ['error'],
|
|
17
|
+
'vue/padding-line-between-blocks': 'error',
|
|
18
|
+
'vue/padding-line-between-tags': [
|
|
19
|
+
'error',
|
|
20
|
+
[
|
|
21
|
+
{
|
|
22
|
+
blankLine: 'always',
|
|
23
|
+
prev: '*',
|
|
24
|
+
next: '*',
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
],
|
|
28
|
+
'vue/block-order': [
|
|
29
|
+
'error',
|
|
30
|
+
{
|
|
31
|
+
order: ['template', 'script', 'style'],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
'vue/no-undef-components': [
|
|
35
|
+
'error',
|
|
36
|
+
{
|
|
37
|
+
ignorePatterns: [
|
|
38
|
+
'PfIcon',
|
|
39
|
+
'RouterLink',
|
|
40
|
+
'i18n-t',
|
|
41
|
+
'trix-editor',
|
|
42
|
+
'trix-toolbar',
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
'vue/html-comment-content-newline': [
|
|
47
|
+
'error',
|
|
48
|
+
{
|
|
49
|
+
singleline: 'ignore',
|
|
50
|
+
multiline: 'always',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
'vue/no-unused-refs': 'error',
|
|
54
|
+
'vue/no-unused-emit-declarations': 'error',
|
|
55
|
+
'vue/no-undef-properties': 'error',
|
|
56
|
+
'vue/no-this-in-before-route-enter': 'error',
|
|
57
|
+
'vue/html-comment-indent': 'error',
|
|
58
|
+
'vue/html-comment-content-spacing': 'error',
|
|
59
|
+
'vue/component-name-in-template-casing': 'warn',
|
|
60
|
+
'vue/multi-word-component-names': 'off',
|
|
61
|
+
'vue/new-line-between-multi-line-property': 2,
|
|
62
|
+
'vue/no-deprecated-slot-attribute': 'off',
|
|
63
|
+
'vue/no-multiple-template-root': 'error',
|
|
64
|
+
'vue/no-unused-properties': [
|
|
65
|
+
'warn',
|
|
66
|
+
{
|
|
67
|
+
groups: ['props', 'data', 'computed', 'methods', 'setup'],
|
|
68
|
+
deepData: false,
|
|
69
|
+
ignorePublicMembers: false,
|
|
70
|
+
unreferencedOptions: [],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
'vue/no-v-html': 'error',
|
|
74
|
+
'vue/eqeqeq': 'error',
|
|
75
|
+
|
|
76
|
+
'vue/array-bracket-newline': ['warn', 'consistent'],
|
|
77
|
+
'vue/array-element-newline': [
|
|
78
|
+
'warn',
|
|
79
|
+
{ ArrayExpression: 'consistent' },
|
|
80
|
+
],
|
|
81
|
+
'vue/arrow-parens': 'off',
|
|
82
|
+
'vue/template-curly-spacing': ['off'],
|
|
83
|
+
|
|
84
|
+
// extensions of stylistic rules applied to the template tag
|
|
85
|
+
'vue/array-bracket-spacing': ['error', 'never'],
|
|
86
|
+
'vue/arrow-spacing': [
|
|
87
|
+
'error',
|
|
88
|
+
{
|
|
89
|
+
before: true,
|
|
90
|
+
after: true,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
'vue/block-spacing': ['error', 'always'],
|
|
94
|
+
'vue/brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
|
95
|
+
'vue/comma-dangle': [
|
|
96
|
+
'error',
|
|
97
|
+
{
|
|
98
|
+
arrays: 'always-multiline',
|
|
99
|
+
objects: 'always-multiline',
|
|
100
|
+
imports: 'always-multiline',
|
|
101
|
+
exports: 'always-multiline',
|
|
102
|
+
functions: 'always-multiline',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
'vue/comma-spacing': [
|
|
106
|
+
'error',
|
|
107
|
+
{
|
|
108
|
+
before: false,
|
|
109
|
+
after: true,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
'vue/dot-location': ['error', 'property'],
|
|
113
|
+
'vue/func-call-spacing': ['error', 'never'],
|
|
114
|
+
'vue/key-spacing': [
|
|
115
|
+
'error',
|
|
116
|
+
{
|
|
117
|
+
beforeColon: false,
|
|
118
|
+
afterColon: true,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
'vue/keyword-spacing': [
|
|
122
|
+
'error',
|
|
123
|
+
{
|
|
124
|
+
before: true,
|
|
125
|
+
after: true,
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
'vue/multiline-ternary': ['error', 'always-multiline'],
|
|
129
|
+
'vue/no-extra-parens': ['error', 'functions'],
|
|
130
|
+
'vue/object-curly-newline': [
|
|
131
|
+
'error',
|
|
132
|
+
{
|
|
133
|
+
multiline: true,
|
|
134
|
+
consistent: true,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
'vue/object-curly-spacing': ['error', 'always'],
|
|
138
|
+
'vue/object-property-newline': 'error',
|
|
139
|
+
'vue/operator-linebreak': [
|
|
140
|
+
'error',
|
|
141
|
+
'after',
|
|
142
|
+
{
|
|
143
|
+
overrides: {
|
|
144
|
+
'?': 'before',
|
|
145
|
+
':': 'before',
|
|
146
|
+
'|>': 'before',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
'vue/space-in-parens': ['error', 'never'],
|
|
151
|
+
'vue/space-infix-ops': 'error',
|
|
152
|
+
'vue/space-unary-ops': [
|
|
153
|
+
'error',
|
|
154
|
+
{
|
|
155
|
+
words: true,
|
|
156
|
+
nonwords: false,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
// IMPORTANT: These rules should be only applied to components, not pages. That's why we filter the files here
|
|
163
|
+
files: ['src/components/**/*'],
|
|
164
|
+
rules: {
|
|
165
|
+
'vue/match-component-file-name': [
|
|
166
|
+
'error',
|
|
167
|
+
{
|
|
168
|
+
extensions: ['vue'],
|
|
169
|
+
shouldMatchCase: true,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
'vue/require-name-property': 'error',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
files: ['src/**/*'], // exclude files from root folder
|
|
177
|
+
plugins: {
|
|
178
|
+
noRelativeImportPathsPlugin,
|
|
179
|
+
},
|
|
180
|
+
rules: {
|
|
181
|
+
'noRelativeImportPathsPlugin/no-relative-import-paths': [
|
|
182
|
+
'error',
|
|
183
|
+
{
|
|
184
|
+
allowSameFolder: false,
|
|
185
|
+
rootDir: 'src',
|
|
186
|
+
prefix: '@',
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
]
|