eslint-plugin-raflint 1.3.4 → 1.4.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 +12 -0
- package/TESTING.md +3 -3
- package/{testExample.js → assets/testExample.js} +2 -2
- package/eslint.config.js +230 -228
- package/index.js +0 -44
- package/package.json +23 -27
- package/rules/noPathJoin.js +12 -17
- package/test/noPathJoin.test.js +22 -2
- package/todo.txt +96 -0
- package/dist/bundle.cjs +0 -66
- package/jest.config.js +0 -4
package/README.md
CHANGED
|
@@ -29,3 +29,15 @@ Les utilisations de `path.join()` avec deux arguments qui peuvent être remplac
|
|
|
29
29
|
qui devrait être écrites comme ça:
|
|
30
30
|
|
|
31
31
|
const filePath = `${directory}/${filename}`;
|
|
32
|
+
|
|
33
|
+
# tester le plugin sur un projet
|
|
34
|
+
|
|
35
|
+
on peut se mettre dans le dossier ou on veut utiliser le plugin pui lancer :
|
|
36
|
+
|
|
37
|
+
npm link ../pathDuPlugin
|
|
38
|
+
on peut ensuite le voir comme ça
|
|
39
|
+
|
|
40
|
+
npm ls --link
|
|
41
|
+
puis enlever le link
|
|
42
|
+
|
|
43
|
+
npm unlink xxx
|
package/TESTING.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Comment tester la règle no-path-join
|
|
2
2
|
## Test manuel avec le fichier d'exemple
|
|
3
3
|
|
|
4
|
-
Un fichier d'exemple `testExample.js` a été créé pour démontrer le fonctionnement de la règle. Pour tester manuellement:
|
|
4
|
+
Un fichier d'exemple `assets/testExample.js` a été créé pour démontrer le fonctionnement de la règle. Pour tester manuellement:
|
|
5
5
|
|
|
6
6
|
1. Vérifier que la règle détecte les problèmes:
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
npx eslint -c eslinttest.config.js testExample.js
|
|
9
|
+
npx eslint -c eslinttest.config.js assets/testExample.js
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Vous devriez voir des erreurs pour les lignes contenant `path.join(directory, filename)` et `path.join(process.cwd(), 'file.txt')`.
|
|
@@ -14,5 +14,5 @@ Vous devriez voir des erreurs pour les lignes contenant `path.join(directory, fi
|
|
|
14
14
|
2. Vérifier que la règle corrige automatiquement le code:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npx eslint -c eslinttest.config.js testExample.js --fix
|
|
17
|
+
npx eslint -c eslinttest.config.js assets/testExample.js --fix
|
|
18
18
|
```
|
|
@@ -7,10 +7,10 @@ const filename = 'file.txt';
|
|
|
7
7
|
const root = '/';
|
|
8
8
|
|
|
9
9
|
// Ce code sera détecté et corrigé par notre règle
|
|
10
|
-
const filePath1 =
|
|
10
|
+
const filePath1 = `${directory}/${filename}`;
|
|
11
11
|
|
|
12
12
|
// Ce code sera détecté et corrigé par notre règle
|
|
13
|
-
const filePath2 =
|
|
13
|
+
const filePath2 = `${process.cwd()}/file.txt`;
|
|
14
14
|
|
|
15
15
|
// Ce code ne sera pas détecté car il a plus de 2 arguments
|
|
16
16
|
const filePath3 = path.join(root, directory, filename);
|
package/eslint.config.js
CHANGED
|
@@ -3,13 +3,11 @@ import unicorn from 'eslint-plugin-unicorn';
|
|
|
3
3
|
import promise from 'eslint-plugin-promise';
|
|
4
4
|
import n from 'eslint-plugin-n';
|
|
5
5
|
import raflint from 'eslint-plugin-raflint';
|
|
6
|
-
import pluginimport from 'eslint-plugin-import';
|
|
6
|
+
import pluginimport from 'eslint-plugin-import-x';
|
|
7
7
|
import babelParser from '@babel/eslint-parser';
|
|
8
8
|
import js from '@eslint/js';
|
|
9
9
|
import globals from 'globals';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
11
|
export default [
|
|
14
12
|
// eslint:recommended,
|
|
15
13
|
js.configs.recommended,
|
|
@@ -30,19 +28,7 @@ export default [
|
|
|
30
28
|
pluginimport.flatConfigs.recommended,
|
|
31
29
|
|
|
32
30
|
{
|
|
33
|
-
ignores: [
|
|
34
|
-
"node_modules/",
|
|
35
|
-
"web/",
|
|
36
|
-
"public/",
|
|
37
|
-
"coverage/",
|
|
38
|
-
"data/",
|
|
39
|
-
"vendor/",
|
|
40
|
-
"cypress/",
|
|
41
|
-
"react/",
|
|
42
|
-
"js/",
|
|
43
|
-
"assets/",
|
|
44
|
-
"**/old/",
|
|
45
|
-
],
|
|
31
|
+
ignores: ['legacy/', 'dist/', 'node_modules/', 'web/', 'public/', 'coverage/', 'data/', 'vendor/', 'react/', 'js/', 'assets/', '**/old/'],
|
|
46
32
|
},
|
|
47
33
|
{
|
|
48
34
|
languageOptions: {
|
|
@@ -53,8 +39,8 @@ export default [
|
|
|
53
39
|
},
|
|
54
40
|
parser: babelParser,
|
|
55
41
|
parserOptions: {
|
|
56
|
-
ecmaVersion:
|
|
57
|
-
sourceType:
|
|
42
|
+
ecmaVersion: 'latest',
|
|
43
|
+
sourceType: 'module',
|
|
58
44
|
requireConfigFile: false,
|
|
59
45
|
},
|
|
60
46
|
},
|
|
@@ -62,223 +48,239 @@ export default [
|
|
|
62
48
|
raflint,
|
|
63
49
|
},
|
|
64
50
|
rules: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"sonarjs/no-infinite-loop": 0,
|
|
77
|
-
"sonarjs/no-hardcoded-ip": 0,
|
|
78
|
-
"sonarjs/pluginRules-of-hooks": 0,
|
|
79
|
-
"sonarjs/sonar-no-fallthrough": 0,
|
|
80
|
-
"sonarjs/no-ignored-exceptions": 0,
|
|
81
|
-
"sonarjs/slow-regex": 0,
|
|
82
|
-
"sonarjs/concise-regex": 0,
|
|
83
|
-
"sonarjs/hashing": 0,
|
|
84
|
-
"sonarjs/no-dead-store": 0,
|
|
85
|
-
"sonarjs/no-unused-vars": 0,
|
|
86
|
-
"sonarjs/no-hardcoded-passwords": 0,
|
|
87
|
-
"sonarjs/no-hardcoded-secrets": 0,
|
|
88
|
-
"sonarjs/unnecessary-character-escapes": 0,
|
|
89
|
-
"sonarjs/pseudo-random": 0,
|
|
90
|
-
"sonarjs/no-os-command-from-path": 0,
|
|
91
|
-
"sonarjs/anchor-precedence": 0,
|
|
92
|
-
"sonarjs/no-nested-functions": 0,
|
|
93
|
-
"sonarjs/new-cap": 0,
|
|
94
|
-
"sonarjs/sql-queries": 0,
|
|
95
|
-
"sonarjs/content-length": 0,
|
|
96
|
-
"sonarjs/no-commented-code": 0,
|
|
97
|
-
"raflint/no-conditional-object-spread": ["error"],
|
|
98
|
-
"raflint/no-path-join": ["error"],
|
|
99
|
-
// "import/no-named-as-default-member": 0,
|
|
100
|
-
"unicorn/prefer-event-target": 0,
|
|
101
|
-
"unicorn/prefer-structured-clone": 0,
|
|
102
|
-
"unicorn/prefer-string-raw": 0,
|
|
103
|
-
"unicorn/no-anonymous-default-export": 0,
|
|
104
|
-
"unicorn/better-regex": 0,
|
|
105
|
-
"unicorn/catch-error-name": 0,
|
|
106
|
-
"unicorn/consistent-function-scoping": 0,
|
|
107
|
-
"unicorn/expiring-todo-comments": 0,
|
|
108
|
-
"unicorn/explicit-length-check": 0,
|
|
109
|
-
"unicorn/import-style": 0,
|
|
110
|
-
"unicorn/no-array-for-each": 0,
|
|
111
|
-
"unicorn/prefer-single-call": 0,
|
|
112
|
-
"unicorn/no-array-reduce": 0,
|
|
113
|
-
"unicorn/no-lonely-if": 0,
|
|
114
|
-
"unicorn/no-negated-condition": 0,
|
|
115
|
-
"unicorn/no-null": 0,
|
|
116
|
-
"unicorn/no-process-exit": 0,
|
|
117
|
-
"unicorn/no-this-assignment": 0,
|
|
118
|
-
"unicorn/no-unnecessary-await": 0,
|
|
119
|
-
"unicorn/no-unused-properties": 0,
|
|
120
|
-
"unicorn/prefer-code-point": 0,
|
|
121
|
-
"unicorn/prefer-default-parameters": 0,
|
|
122
|
-
"unicorn/prefer-export-from": 0,
|
|
123
|
-
"unicorn/prefer-native-coercion-functions": 0,
|
|
124
|
-
"unicorn/prefer-number-properties": 0,
|
|
125
|
-
"unicorn/prefer-set-has": 0,
|
|
126
|
-
"unicorn/prefer-set-size": 0,
|
|
127
|
-
"unicorn/prefer-spread": 0,
|
|
128
|
-
"unicorn/prefer-string-replace-all": 0,
|
|
129
|
-
"unicorn/prefer-string-slice": 0,
|
|
130
|
-
"unicorn/prefer-switch": 0,
|
|
131
|
-
"unicorn/prefer-ternary": 0,
|
|
132
|
-
"unicorn/prefer-top-level-await": 0,
|
|
133
|
-
"unicorn/prevent-abbreviations": 0,
|
|
134
|
-
"unicorn/relative-url-style": 0,
|
|
135
|
-
"unicorn/switch-case-braces": 0,
|
|
136
|
-
"unicorn/template-indent": 0,
|
|
137
|
-
"unicorn/text-encoding-identifier-case": 0,
|
|
138
|
-
"unicorn/prefer-regexp-test": 0,
|
|
139
|
-
"unicorn/prefer-optional-catch-binding": 0,
|
|
140
|
-
"unicorn/filename-case": [
|
|
141
|
-
"error",
|
|
51
|
+
'sonarjs/no-empty-function': 0,
|
|
52
|
+
'sonarjs/no-unused-expressions': 0,
|
|
53
|
+
'sonarjs/no-unsafe-unzip': 0,
|
|
54
|
+
'sonarjs/os-command': 0,
|
|
55
|
+
'sonarjs/cors': 0,
|
|
56
|
+
'sonarjs/publicly-writable-directories': 0,
|
|
57
|
+
'sonarjs/file-permissions': 0,
|
|
58
|
+
'sonarjs/no-empty-test-file': 0,
|
|
59
|
+
'import-x/no-named-as-default-member': 0,
|
|
60
|
+
'import-x/no-unresolved': [
|
|
61
|
+
'error',
|
|
142
62
|
{
|
|
143
|
-
|
|
144
|
-
|
|
63
|
+
ignore: [
|
|
64
|
+
'^yargs/helpers$',
|
|
65
|
+
'^p-queue$',
|
|
66
|
+
'^@vitejs/plugin-react$',
|
|
67
|
+
'^public-ip$',
|
|
68
|
+
'^@modelcontextprotocol/sdk/',
|
|
69
|
+
'^@maizzle/framework$',
|
|
70
|
+
'^file-type$',
|
|
71
|
+
'^vite$',
|
|
72
|
+
'^windows-1252$',
|
|
73
|
+
'^csv-parse/sync$'
|
|
74
|
+
],
|
|
75
|
+
},
|
|
145
76
|
],
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
77
|
+
'sonarjs/regex-complexity': 0,
|
|
78
|
+
'sonarjs/no-clear-text-protocols': 0,
|
|
79
|
+
'sonarjs/no-infinite-loop': 0,
|
|
80
|
+
'sonarjs/no-hardcoded-ip': 0,
|
|
81
|
+
'sonarjs/pluginRules-of-hooks': 0,
|
|
82
|
+
'sonarjs/sonar-no-fallthrough': 0,
|
|
83
|
+
'sonarjs/no-ignored-exceptions': 0,
|
|
84
|
+
'sonarjs/slow-regex': 0,
|
|
85
|
+
'sonarjs/concise-regex': 0,
|
|
86
|
+
'sonarjs/hashing': 0,
|
|
87
|
+
'sonarjs/no-dead-store': 0,
|
|
88
|
+
'sonarjs/no-unused-vars': 0,
|
|
89
|
+
'sonarjs/no-hardcoded-passwords': 0,
|
|
90
|
+
'sonarjs/no-hardcoded-secrets': 0,
|
|
91
|
+
'sonarjs/unnecessary-character-escapes': 0,
|
|
92
|
+
'sonarjs/pseudo-random': 0,
|
|
93
|
+
'sonarjs/no-os-command-from-path': 0,
|
|
94
|
+
'sonarjs/anchor-precedence': 0,
|
|
95
|
+
'sonarjs/no-nested-functions': 0,
|
|
96
|
+
'sonarjs/new-cap': 0,
|
|
97
|
+
'sonarjs/sql-queries': 0,
|
|
98
|
+
'sonarjs/content-length': 0,
|
|
99
|
+
'sonarjs/no-commented-code': 0,
|
|
100
|
+
'raflint/no-conditional-object-spread': ['error'],
|
|
101
|
+
'raflint/no-path-join': ['error'],
|
|
102
|
+
'unicorn/prefer-event-target': 0,
|
|
103
|
+
'unicorn/prefer-structured-clone': 0,
|
|
104
|
+
'unicorn/prefer-string-raw': 0,
|
|
105
|
+
'unicorn/no-anonymous-default-export': 0,
|
|
106
|
+
'unicorn/better-regex': 0,
|
|
107
|
+
'unicorn/catch-error-name': 0,
|
|
108
|
+
'unicorn/consistent-function-scoping': 0,
|
|
109
|
+
'unicorn/expiring-todo-comments': 0,
|
|
110
|
+
'unicorn/explicit-length-check': 0,
|
|
111
|
+
'unicorn/import-style': 0,
|
|
112
|
+
'unicorn/no-array-for-each': 0,
|
|
113
|
+
'unicorn/prefer-single-call': 0,
|
|
114
|
+
'unicorn/no-array-reduce': 0,
|
|
115
|
+
'unicorn/no-lonely-if': 0,
|
|
116
|
+
'unicorn/no-negated-condition': 0,
|
|
117
|
+
'unicorn/no-null': 0,
|
|
118
|
+
'unicorn/no-process-exit': 0,
|
|
119
|
+
'unicorn/no-this-assignment': 0,
|
|
120
|
+
'unicorn/no-unnecessary-await': 0,
|
|
121
|
+
'unicorn/no-unused-properties': 0,
|
|
122
|
+
'unicorn/prefer-code-point': 0,
|
|
123
|
+
'unicorn/prefer-default-parameters': 0,
|
|
124
|
+
'unicorn/prefer-export-from': 0,
|
|
125
|
+
'unicorn/prefer-native-coercion-functions': 0,
|
|
126
|
+
'unicorn/prefer-number-properties': 0,
|
|
127
|
+
'unicorn/prefer-set-has': 0,
|
|
128
|
+
'unicorn/prefer-set-size': 0,
|
|
129
|
+
'unicorn/prefer-spread': 0,
|
|
130
|
+
'unicorn/prefer-string-replace-all': 0,
|
|
131
|
+
'unicorn/prefer-string-slice': 0,
|
|
132
|
+
'unicorn/prefer-switch': 0,
|
|
133
|
+
'unicorn/prefer-ternary': 0,
|
|
134
|
+
'unicorn/prefer-top-level-await': 0,
|
|
135
|
+
'unicorn/prevent-abbreviations': 0,
|
|
136
|
+
'unicorn/consistent-compound-words': 0,
|
|
137
|
+
// ne pas retirer `undefined` passe en argument (souvent requis par la signature -> casse tsc)
|
|
138
|
+
'unicorn/no-useless-undefined': ['error', { checkArguments: false }],
|
|
139
|
+
'unicorn/relative-url-style': 0,
|
|
140
|
+
'unicorn/switch-case-braces': 0,
|
|
141
|
+
'unicorn/template-indent': 0,
|
|
142
|
+
'unicorn/text-encoding-identifier-case': 0,
|
|
143
|
+
'unicorn/prefer-regexp-test': 0,
|
|
144
|
+
'unicorn/prefer-optional-catch-binding': 0,
|
|
145
|
+
'unicorn/filename-case': 0,
|
|
146
|
+
'sonarjs/cognitive-complexity': 0,
|
|
147
|
+
'sonarjs/no-nested-template-literals': 0,
|
|
148
|
+
'sonarjs/no-collapsible-if': 0,
|
|
149
|
+
'sonarjs/no-duplicate-string': 0,
|
|
150
|
+
'sonarjs/prefer-immediate-return': 0,
|
|
151
|
+
'sonarjs/no-identical-functions': 0,
|
|
152
|
+
'sonarjs/prefer-object-literal': 0,
|
|
153
|
+
'sonarjs/prefer-single-boolean-return': 0,
|
|
154
|
+
'n/no-unpublished-import': 0,
|
|
155
|
+
'n/no-unsupported-features/es-syntax': 0,
|
|
156
|
+
'n/no-unsupported-features/node-builtins': 0,
|
|
157
|
+
'n/no-missing-import': 0,
|
|
158
|
+
'n/no-process-exit': 0,
|
|
159
|
+
|
|
159
160
|
// si on l'active ça pose pb dans check / automerge
|
|
160
|
-
|
|
161
|
+
'n/shebang': 0,
|
|
161
162
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
'one-var-declaration-per-line': ['error', 'always'],
|
|
164
|
+
'one-var': ['error', 'never'],
|
|
165
|
+
'no-unused-expressions': 'error',
|
|
166
|
+
'no-nested-ternary': 'error',
|
|
167
|
+
'no-use-before-define': [
|
|
168
|
+
'error',
|
|
168
169
|
{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
170
|
+
functions: false,
|
|
171
|
+
classes: false,
|
|
172
|
+
variables: true,
|
|
173
|
+
allowNamedExports: false,
|
|
174
|
+
},
|
|
174
175
|
],
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
176
|
+
'no-new-native-nonconstructor': 'error',
|
|
177
|
+
'no-empty-static-block': 'error',
|
|
178
|
+
'symbol-description': 'error',
|
|
179
|
+
'require-yield': 'error',
|
|
180
|
+
'prefer-spread': 'error',
|
|
181
|
+
'prefer-rest-params': 'error',
|
|
182
|
+
'prefer-object-spread': 'error',
|
|
183
|
+
'prefer-object-has-own': 'error',
|
|
184
|
+
'prefer-numeric-literals': 'error',
|
|
185
|
+
'prefer-exponentiation-operator': 'error',
|
|
186
|
+
'operator-assignment': 'error',
|
|
187
|
+
'no-useless-rename': 'error',
|
|
188
|
+
'no-useless-constructor': 'error',
|
|
189
|
+
'no-useless-computed-key': 'error',
|
|
190
|
+
'no-unused-labels': 'error',
|
|
191
|
+
'no-script-url': 'error',
|
|
192
|
+
'no-new-object': 'error',
|
|
193
|
+
'no-multi-assign': 'error',
|
|
194
|
+
'no-loop-func': 'error',
|
|
195
|
+
'no-inline-comments': 'error',
|
|
196
|
+
'no-implicit-coercion': 'error',
|
|
197
|
+
'no-extra-boolean-cast': 'error',
|
|
198
|
+
'no-confusing-arrow': 'error',
|
|
199
|
+
'no-case-declarations': 'error',
|
|
200
|
+
'no-bitwise': 'error',
|
|
201
|
+
'no-array-constructor': 'error',
|
|
202
|
+
'no-alert': 'error',
|
|
203
|
+
'logical-assignment-operators': 'error',
|
|
204
|
+
'grouped-accessor-pairs': 'error',
|
|
205
|
+
'func-name-matching': 'error',
|
|
206
|
+
'dot-notation': 'error',
|
|
207
|
+
'consistent-this': ['error', 'self'],
|
|
208
|
+
'accessor-pairs': 'error',
|
|
209
|
+
'no-unused-private-class-members': 'error',
|
|
210
|
+
'no-promise-executor-return': 'error',
|
|
211
|
+
'no-duplicate-imports': 'error',
|
|
212
|
+
'no-constant-binary-expression': 'error',
|
|
213
|
+
'no-undef-init': 'error',
|
|
214
|
+
'no-label-var': 'error',
|
|
215
|
+
'init-declarations': ['error', 'always'],
|
|
216
|
+
'wrap-iife': ['error', 'inside'],
|
|
217
|
+
yoda: 'error',
|
|
218
|
+
'vars-on-top': 'error',
|
|
219
|
+
radix: ['error', 'as-needed'],
|
|
220
|
+
'prefer-regex-literals': 'error',
|
|
221
|
+
'prefer-promise-reject-errors': 'error',
|
|
222
|
+
'promise/catch-or-return': ['error', { terminationMethod: ['catch', 'finally'] }],
|
|
223
|
+
'no-warning-comments': 'error',
|
|
224
|
+
'no-void': 'error',
|
|
225
|
+
'no-useless-return': 'error',
|
|
226
|
+
'no-useless-concat': 'error',
|
|
227
|
+
'no-useless-call': 'error',
|
|
228
|
+
'no-throw-literal': 'error',
|
|
229
|
+
'no-sequences': 'error',
|
|
230
|
+
'no-self-compare': 'error',
|
|
231
|
+
'no-return-assign': 'error',
|
|
232
|
+
'no-proto': 'error',
|
|
233
|
+
'no-octal-escape': 'error',
|
|
234
|
+
'no-nonoctal-decimal-escape': 'error',
|
|
235
|
+
'no-new-wrappers': 'error',
|
|
236
|
+
'no-new-func': 'error',
|
|
237
|
+
'no-new': 'error',
|
|
238
|
+
'no-multi-str': 'error',
|
|
239
|
+
'no-multi-spaces': 'error',
|
|
240
|
+
'no-lone-blocks': 'error',
|
|
241
|
+
'no-labels': 'error',
|
|
242
|
+
'no-iterator': 'error',
|
|
243
|
+
'no-empty-function': 'error',
|
|
244
|
+
'block-scoped-var': 'error',
|
|
245
|
+
'prefer-arrow-callback': 'error',
|
|
246
|
+
'no-implied-eval': 'error',
|
|
247
|
+
'no-implicit-globals': 'error',
|
|
248
|
+
'no-floating-decimal': 'error',
|
|
249
|
+
'no-extra-label': 'error',
|
|
250
|
+
'no-extra-bind': 'error',
|
|
251
|
+
'no-extend-native': [
|
|
252
|
+
'error',
|
|
251
253
|
{
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
+
exceptions: ['Object'],
|
|
255
|
+
},
|
|
254
256
|
],
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
257
|
+
'no-eval': 'error',
|
|
258
|
+
'no-constant-condition': ['error', { checkLoops: false }],
|
|
259
|
+
'no-eq-null': 'error',
|
|
260
|
+
'no-else-return': 'error',
|
|
261
|
+
'no-unused-vars': 0,
|
|
262
|
+
'no-console': 0,
|
|
263
|
+
'no-empty': 0,
|
|
264
|
+
'no-redeclare': 0,
|
|
265
|
+
'no-useless-escape': 0,
|
|
266
|
+
'no-var': 'error',
|
|
267
|
+
'object-shorthand': ['error', 'properties'],
|
|
268
|
+
'prefer-template': 'error',
|
|
269
|
+
'no-div-regex': 'error',
|
|
270
|
+
'no-constructor-return': 'error',
|
|
271
|
+
'no-caller': 'error',
|
|
272
|
+
'max-classes-per-file': 'error',
|
|
273
|
+
'default-param-last': 'error',
|
|
274
|
+
'default-case-last': 'error',
|
|
275
|
+
'default-case': 'error',
|
|
276
|
+
'array-callback-return': 'error',
|
|
277
|
+
'no-unsafe-optional-chaining': 'error',
|
|
278
|
+
'no-unreachable-loop': 'error',
|
|
279
|
+
'no-template-curly-in-string': 'error',
|
|
280
|
+
'no-loss-of-precision': 'error',
|
|
281
|
+
'no-inner-declarations': 0,
|
|
282
|
+
'no-process-exit': 0,
|
|
283
|
+
'prefer-const': ['error', { destructuring: 'all' }],
|
|
282
284
|
},
|
|
283
|
-
}
|
|
285
|
+
},
|
|
284
286
|
];
|
package/index.js
CHANGED
|
@@ -7,47 +7,3 @@ export default {
|
|
|
7
7
|
'no-path-join': noPathJoin,
|
|
8
8
|
},
|
|
9
9
|
};
|
|
10
|
-
|
|
11
|
-
/*
|
|
12
|
-
import path from 'node:path';
|
|
13
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
import fs from 'node:fs';
|
|
16
|
-
const { name, version } = JSON.parse(await fs.promises.readFile(`${__dirname}/package.json`));
|
|
17
|
-
|
|
18
|
-
import noConditionalObjectSpread from './rules/noConditionalObjectSpread.js';
|
|
19
|
-
import noPathJoin from './rules/noPathJoin.js';
|
|
20
|
-
|
|
21
|
-
const rules = {
|
|
22
|
-
'no-conditional-object-spread': noConditionalObjectSpread,
|
|
23
|
-
'no-path-join': noPathJoin,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default {
|
|
27
|
-
meta: {
|
|
28
|
-
name,
|
|
29
|
-
version,
|
|
30
|
-
},
|
|
31
|
-
rules,
|
|
32
|
-
configs: {
|
|
33
|
-
'flat/recommended': {
|
|
34
|
-
plugins: {
|
|
35
|
-
raflint: {
|
|
36
|
-
meta: {
|
|
37
|
-
name,
|
|
38
|
-
version,
|
|
39
|
-
},
|
|
40
|
-
rules: {
|
|
41
|
-
'raflint/no-conditional-object-spread': "error",
|
|
42
|
-
'raflint/no-path-join': "error"
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
rules: {
|
|
47
|
-
'raflint/no-conditional-object-spread': "error",
|
|
48
|
-
'raflint/no-path-join': "error"
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-raflint",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "",
|
|
6
6
|
"keywords": [],
|
|
@@ -11,42 +11,38 @@
|
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"author": "Raphael Piccolo",
|
|
13
13
|
"type": "module",
|
|
14
|
-
"exports":
|
|
15
|
-
".": {
|
|
16
|
-
"require": "./dist/bundle.cjs",
|
|
17
|
-
"import": "./index.js"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
14
|
+
"exports": "./index.js",
|
|
20
15
|
"scripts": {
|
|
21
16
|
"cov": "c8 npm run test",
|
|
22
|
-
"jest": "SILENT=1 node --no-warnings --experimental-vm-modules ./node_modules/.bin/jest",
|
|
23
17
|
"prepare": "husky",
|
|
24
|
-
"test": "SILENT=1 mocha --timeout 15000 {lib
|
|
18
|
+
"test": "SILENT=1 mocha --timeout 15000 {,lib/**/,test/**/}*.test.js"
|
|
25
19
|
},
|
|
26
20
|
"dependencies": {
|
|
27
|
-
"@babel/eslint-parser": "^
|
|
28
|
-
"
|
|
29
|
-
"eslint": "^
|
|
30
|
-
"eslint-plugin-
|
|
31
|
-
"eslint-plugin-sonarjs": "^3.0.2",
|
|
32
|
-
"eslint-plugin-unicorn": "^59.0.0"
|
|
21
|
+
"@babel/eslint-parser": "^8.0.0",
|
|
22
|
+
"eslint-plugin-n": "^18.1.0",
|
|
23
|
+
"eslint-plugin-sonarjs": "^4.0.3",
|
|
24
|
+
"eslint-plugin-unicorn": "^67.0.0"
|
|
33
25
|
},
|
|
34
26
|
"devDependencies": {
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"eslint
|
|
39
|
-
"eslint-plugin-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
27
|
+
"@eslint/js": "^10.0.1",
|
|
28
|
+
"@stoplight/spectral-cli": "^6.16.0",
|
|
29
|
+
"c8": "^11.0.0",
|
|
30
|
+
"eslint": "^10.5.0",
|
|
31
|
+
"eslint-plugin-import-x": "^4.16.2",
|
|
32
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
33
|
+
"eslint-plugin-raflint": "^1.4.0",
|
|
34
|
+
"globals": "^17.6.0",
|
|
42
35
|
"husky": "^9.1.7",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
36
|
+
"lint-staged": "^17.0.7",
|
|
37
|
+
"markdownlint": "^0.41.0",
|
|
38
|
+
"mocha": "^11.7.6",
|
|
39
|
+
"prettier": "^3.8.4",
|
|
40
|
+
"ts-api-utils": "^2.5.0"
|
|
48
41
|
},
|
|
49
42
|
"engines": {
|
|
50
43
|
"node": ">=21.0.0"
|
|
44
|
+
},
|
|
45
|
+
"allowScripts": {
|
|
46
|
+
"unrs-resolver": true
|
|
51
47
|
}
|
|
52
48
|
}
|
package/rules/noPathJoin.js
CHANGED
|
@@ -2,7 +2,7 @@ export default {
|
|
|
2
2
|
meta: {
|
|
3
3
|
type: 'suggestion',
|
|
4
4
|
docs: {
|
|
5
|
-
description: 'Disallow path.join(
|
|
5
|
+
description: 'Disallow path.join() in favor of template strings',
|
|
6
6
|
category: 'Stylistic Issues',
|
|
7
7
|
recommended: true,
|
|
8
8
|
},
|
|
@@ -12,27 +12,22 @@ export default {
|
|
|
12
12
|
create(context) {
|
|
13
13
|
return {
|
|
14
14
|
CallExpression(node) {
|
|
15
|
-
// Vérifier si c'est un appel à path.join
|
|
16
15
|
if (
|
|
17
16
|
node.callee.type === 'MemberExpression' &&
|
|
18
17
|
node.callee.object.name === 'path' &&
|
|
19
18
|
node.callee.property.name === 'join' &&
|
|
20
|
-
|
|
21
|
-
node.arguments.length === 2
|
|
19
|
+
node.arguments.length >= 2
|
|
22
20
|
) {
|
|
23
|
-
const sourceCode = context.getSourceCode();
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// Sinon, utiliser le format standard avec ${}
|
|
34
|
-
replacement = `\`\${${arg1}}/\${${arg2}}\``;
|
|
35
|
-
}
|
|
21
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
22
|
+
|
|
23
|
+
const parts = node.arguments.map((arg) => {
|
|
24
|
+
if (arg.type === 'Literal' && typeof arg.value === 'string') {
|
|
25
|
+
return arg.value;
|
|
26
|
+
}
|
|
27
|
+
return `\${${sourceCode.getText(arg)}}`;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const replacement = `\`${parts.join('/')}\``;
|
|
36
31
|
|
|
37
32
|
context.report({
|
|
38
33
|
node,
|
package/test/noPathJoin.test.js
CHANGED
|
@@ -23,9 +23,9 @@ ruleTester.run('no-path-join', noPathJoin, {
|
|
|
23
23
|
`,
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
// Cas avec
|
|
26
|
+
// Cas avec un seul argument (non concerné)
|
|
27
27
|
code: `
|
|
28
|
-
const filePath = path.join(
|
|
28
|
+
const filePath = path.join(directory);
|
|
29
29
|
`,
|
|
30
30
|
},
|
|
31
31
|
{
|
|
@@ -54,5 +54,25 @@ ruleTester.run('no-path-join', noPathJoin, {
|
|
|
54
54
|
const filePath = \`\${process.cwd()}/file.txt\`;
|
|
55
55
|
`,
|
|
56
56
|
},
|
|
57
|
+
{
|
|
58
|
+
// 3 arguments
|
|
59
|
+
code: `
|
|
60
|
+
const filePath = path.join(root, directory, filename);
|
|
61
|
+
`,
|
|
62
|
+
errors: [{ message: 'Utilisez des template strings au lieu de path.join() pour la concaténation de chemins simples' }],
|
|
63
|
+
output: `
|
|
64
|
+
const filePath = \`\${root}/\${directory}/\${filename}\`;
|
|
65
|
+
`,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
// Mix variables et littéraux
|
|
69
|
+
code: `
|
|
70
|
+
const filePath = path.join(root, 'uploads', filename);
|
|
71
|
+
`,
|
|
72
|
+
errors: [{ message: 'Utilisez des template strings au lieu de path.join() pour la concaténation de chemins simples' }],
|
|
73
|
+
output: `
|
|
74
|
+
const filePath = \`\${root}/uploads/\${filename}\`;
|
|
75
|
+
`,
|
|
76
|
+
},
|
|
57
77
|
],
|
|
58
78
|
});
|
package/todo.txt
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
REVIEW DE CODE — 2026-04-26
|
|
2
|
+
============================================
|
|
3
|
+
|
|
4
|
+
Plugin ESLint custom maison. Expose 2 regles :
|
|
5
|
+
- `no-conditional-object-spread` : interdit `{...(cond ? {x:1} : {})}`
|
|
6
|
+
et `{...(cond && {x:1})}`
|
|
7
|
+
- `no-path-join` : interdit `path.join(a, b)` au profit de
|
|
8
|
+
`\`${a}/${b}\`` (avec autofix).
|
|
9
|
+
|
|
10
|
+
13+43 lignes de code metier dans rules/, 124 lignes de tests, 53
|
|
11
|
+
lignes (dont 42 commentees) dans index.js.
|
|
12
|
+
|
|
13
|
+
BUGS / FRAGILITE
|
|
14
|
+
----------------
|
|
15
|
+
[ ] index.js : 42 lignes commentees (CRITIQUE de lisibilite)
|
|
16
|
+
index.js:11-53 : tout un bloc commente avec une version
|
|
17
|
+
"améliorée" du plugin (avec `meta.name`, `meta.version`,
|
|
18
|
+
`configs.flat/recommended`). C'est probablement la version
|
|
19
|
+
"qui marche" sur ESLint 9 flat config, mais elle est commentee.
|
|
20
|
+
L'export actuel (lignes 1-9) est minimal et ne suit pas la
|
|
21
|
+
convention ESLint `meta` (manque name/version). Si ESLint
|
|
22
|
+
detecte le plugin sans meta, certains checks (cache, dedup)
|
|
23
|
+
sont degrades.
|
|
24
|
+
A clarifier : soit reactiver le bloc commente (et garder une
|
|
25
|
+
seule version), soit delete le bloc inutile.
|
|
26
|
+
|
|
27
|
+
[ ] noPathJoin : autofix n'introduit pas de slash safe
|
|
28
|
+
rules/noPathJoin.js:25-27 : `parts.join('/')`. Si l'argument
|
|
29
|
+
est `path.join(__dirname, '..', 'file.js')`, le fix produit
|
|
30
|
+
`\`${__dirname}/../file.js\``. OK.
|
|
31
|
+
Mais si l'argument contient un slash final/début, doublon :
|
|
32
|
+
`path.join('a/', 'b')` => `\`a//b\`` (autofix incorrect).
|
|
33
|
+
Path.join normalise les slashs, le fix non. Edge case rare
|
|
34
|
+
mais reel.
|
|
35
|
+
|
|
36
|
+
[ ] noPathJoin : detection MemberExpression chain
|
|
37
|
+
rules/noPathJoin.js:13 : `node.callee.object.name === 'path'`.
|
|
38
|
+
Si import `import { join } from 'node:path'` et utilise
|
|
39
|
+
`join(a, b)`, pas detecte (pas de `path.join`). Fragmentation
|
|
40
|
+
incomplete.
|
|
41
|
+
|
|
42
|
+
[ ] noPathJoin : detection seulement "path.join(>=2 args)"
|
|
43
|
+
rules/noPathJoin.js:14 : `node.arguments.length >= 2`. Si
|
|
44
|
+
`path.join(a)` (1 seul arg), pas declenche. Mais `path.join
|
|
45
|
+
(a)` est en pratique inutile (path.join('foo') === 'foo'),
|
|
46
|
+
une regle pourrait suggerer de retirer l'appel.
|
|
47
|
+
|
|
48
|
+
[ ] noPathJoin : pas de skip pour les cas corrects
|
|
49
|
+
Si l'utilisateur a deliberement choisi `path.join` pour la
|
|
50
|
+
portabilité Windows (`\\` vs `/`), le fix le casse.
|
|
51
|
+
Convention de la stack : tout est sur Linux donc OK, mais
|
|
52
|
+
a documenter (cf README).
|
|
53
|
+
|
|
54
|
+
[ ] noConditionalObjectSpread : detection trop large
|
|
55
|
+
rules/noConditionalObjectSpread.js:5 : `node.argument.type
|
|
56
|
+
=== 'ConditionalExpression' || 'LogicalExpression'`.
|
|
57
|
+
Detecte aussi :
|
|
58
|
+
const obj = { ...(a || b) };
|
|
59
|
+
qui est un usage VALIDE (a est preferable, sinon b). Faux
|
|
60
|
+
positif. A affiner : check si une des branches est `{}` ou
|
|
61
|
+
null/undefined.
|
|
62
|
+
|
|
63
|
+
[ ] noConditionalObjectSpread : pas d'autofix
|
|
64
|
+
Pas `fixable: 'code'`. Le user doit refactor a la main. Bon
|
|
65
|
+
point puisque le refactor change la semantique (variable de
|
|
66
|
+
sortie modifiee), mais le message d'erreur ne propose pas
|
|
67
|
+
d'alternative claire.
|
|
68
|
+
|
|
69
|
+
[ ] noConditionalObjectSpread : pas de meta
|
|
70
|
+
rules/noConditionalObjectSpread.js : pas de `meta` block.
|
|
71
|
+
Manque `meta.docs.description`, `meta.type`, etc. ESLint
|
|
72
|
+
plant pas, mais best practice.
|
|
73
|
+
|
|
74
|
+
CODE MORT / POLLUTION
|
|
75
|
+
---------------------
|
|
76
|
+
[ ] assets/testExample.js
|
|
77
|
+
Fichier de test manuel. OK pour la documentation.
|
|
78
|
+
|
|
79
|
+
[ ] TESTING.md
|
|
80
|
+
Documentation manuelle separee. A consolider dans README.md.
|
|
81
|
+
|
|
82
|
+
CONVENTIONS
|
|
83
|
+
-----------
|
|
84
|
+
[ ] Mauvaise pratique : meta block manquant sur noConditionalObjectSpread
|
|
85
|
+
Cf bugs.
|
|
86
|
+
|
|
87
|
+
[ ] Pas de versioning des rules
|
|
88
|
+
1.4.0 mais pas de breaking change tracking. Si on rend la
|
|
89
|
+
detection plus stricte, casse les CI des consommateurs.
|
|
90
|
+
|
|
91
|
+
DECISION SUGGEREE
|
|
92
|
+
-----------------
|
|
93
|
+
[ ] Trancher index.js : la version commentee semble plus complete.
|
|
94
|
+
Migrer vers la version commentee (avec meta + configs/flat/
|
|
95
|
+
recommended), tester sur 2-3 projets consommateurs, release
|
|
96
|
+
1.5.0.
|
package/dist/bundle.cjs
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
rules: {
|
|
3
|
-
'no-conditional-object-spread': {
|
|
4
|
-
create(context) {
|
|
5
|
-
return {
|
|
6
|
-
SpreadElement(node) {
|
|
7
|
-
if (node.argument.type === 'ConditionalExpression' || node.argument.type === 'LogicalExpression') {
|
|
8
|
-
context.report({
|
|
9
|
-
node,
|
|
10
|
-
message: 'Conditional object spread is not allowed.',
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
'no-path-join': {
|
|
18
|
-
meta: {
|
|
19
|
-
type: 'suggestion',
|
|
20
|
-
docs: {
|
|
21
|
-
description: 'Disallow path.join(a, b) in favor of template strings',
|
|
22
|
-
category: 'Stylistic Issues',
|
|
23
|
-
recommended: true,
|
|
24
|
-
},
|
|
25
|
-
fixable: 'code',
|
|
26
|
-
schema: [],
|
|
27
|
-
},
|
|
28
|
-
create(context) {
|
|
29
|
-
return {
|
|
30
|
-
CallExpression(node) {
|
|
31
|
-
// Vérifier si c'est un appel à path.join
|
|
32
|
-
if (
|
|
33
|
-
node.callee.type === 'MemberExpression' &&
|
|
34
|
-
node.callee.object.name === 'path' &&
|
|
35
|
-
node.callee.property.name === 'join' &&
|
|
36
|
-
// Uniquement pour les cas avec exactement 2 arguments
|
|
37
|
-
node.arguments.length === 2
|
|
38
|
-
) {
|
|
39
|
-
const sourceCode = context.getSourceCode();
|
|
40
|
-
const arg1 = sourceCode.getText(node.arguments[0]);
|
|
41
|
-
const arg2 = sourceCode.getText(node.arguments[1]);
|
|
42
|
-
|
|
43
|
-
// Vérifier si le second argument est une chaîne littérale
|
|
44
|
-
let replacement;
|
|
45
|
-
if (node.arguments[1].type === 'Literal' && typeof node.arguments[1].value === 'string') {
|
|
46
|
-
// Si c'est une chaîne littérale, l'inclure directement sans ${}
|
|
47
|
-
replacement = `\`\${${arg1}}/${node.arguments[1].value}\``;
|
|
48
|
-
} else {
|
|
49
|
-
// Sinon, utiliser le format standard avec ${}
|
|
50
|
-
replacement = `\`\${${arg1}}/\${${arg2}}\``;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
context.report({
|
|
54
|
-
node,
|
|
55
|
-
message: 'Utilisez des template strings au lieu de path.join() pour la concaténation de chemins simples',
|
|
56
|
-
fix(fixer) {
|
|
57
|
-
return fixer.replaceText(node, replacement);
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
};
|
package/jest.config.js
DELETED