@rotki/eslint-plugin 1.3.1 → 1.4.0
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 +3 -15
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +429 -264
- package/package.json +26 -25
package/README.md
CHANGED
|
@@ -38,11 +38,9 @@ export default [
|
|
|
38
38
|
|
|
39
39
|
Or configure individual rules:
|
|
40
40
|
|
|
41
|
-
<!-- eslint-disable perfectionist/sort-imports -->
|
|
42
|
-
|
|
43
41
|
```js
|
|
44
|
-
import * as jsoncParser from 'jsonc-eslint-parser';
|
|
45
42
|
import rotkiPlugin from '@rotki/eslint-plugin';
|
|
43
|
+
import * as jsoncParser from 'jsonc-eslint-parser';
|
|
46
44
|
|
|
47
45
|
export default [
|
|
48
46
|
{
|
|
@@ -62,20 +60,10 @@ export default [
|
|
|
62
60
|
];
|
|
63
61
|
```
|
|
64
62
|
|
|
65
|
-
<!-- eslint-enable perfectionist/sort-imports -->
|
|
66
|
-
|
|
67
63
|
## Rules
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
| [consistent-ref-type-annotation](https://rotki.github.io/eslint-plugin/rules/consistent-ref-type-annotation) | Ensures consistent type annotation position for ref, computed assignments | :black_nib: |
|
|
72
|
-
| [max-dependencies](https://rotki.github.io/eslint-plugin/rules/max-dependencies) | Enforce a maximum number of dependencies per file | |
|
|
73
|
-
| [no-deprecated-classes](https://rotki.github.io/eslint-plugin/rules/no-deprecated-classes) | Disallow deprecated vuetify css classes | :black_nib: |
|
|
74
|
-
| [no-deprecated-components](https://rotki.github.io/eslint-plugin/rules/no-deprecated-components) | Disallow deprecated components | :black_nib: |
|
|
75
|
-
| [no-deprecated-props](https://rotki.github.io/eslint-plugin/rules/no-deprecated-props) | Replace deprecated props with their replacements | :black_nib: |
|
|
76
|
-
| [no-dot-ts-imports](https://rotki.github.io/eslint-plugin/rules/no-dot-ts-imports) | Disallow .ts extension in import statements | :black_nib: |
|
|
77
|
-
| [no-legacy-library-import](https://rotki.github.io/eslint-plugin/rules/no-legacy-library-import) | Disallow imports from @rotki/ui-library-compat | :black_nib: |
|
|
78
|
-
| [no-unused-i18n-keys](https://rotki.github.io/eslint-plugin/rules/no-unused-i18n-keys) | Disallow unused i18n keys in locale files | :black_nib: |
|
|
65
|
+
See the [full list of available rules](https://rotki.github.io/eslint-plugin/rules/),
|
|
66
|
+
including which are enabled by the `recommended` preset and which are auto-fixable.
|
|
79
67
|
|
|
80
68
|
## Documentation
|
|
81
69
|
|
package/dist/index.d.mts
CHANGED
|
@@ -27,6 +27,7 @@ type Options$3 = [{
|
|
|
27
27
|
|
|
28
28
|
type Options$2 = [{
|
|
29
29
|
autofix?: boolean;
|
|
30
|
+
writablePrefixes?: string[];
|
|
30
31
|
}];
|
|
31
32
|
|
|
32
33
|
type Options$1 = [{
|
|
@@ -57,6 +58,7 @@ declare const plugin: {
|
|
|
57
58
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
58
59
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
59
60
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
61
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
60
62
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
61
63
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
62
64
|
};
|
|
@@ -82,6 +84,7 @@ declare const _default: {
|
|
|
82
84
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
83
85
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
84
86
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
87
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
85
88
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
86
89
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
87
90
|
};
|
|
@@ -109,6 +112,7 @@ declare const _default: {
|
|
|
109
112
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
110
113
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
111
114
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
115
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
112
116
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
113
117
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
114
118
|
};
|
|
@@ -145,6 +149,7 @@ declare const _default: {
|
|
|
145
149
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
146
150
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
147
151
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
152
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
148
153
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
149
154
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
150
155
|
};
|
|
@@ -181,6 +186,7 @@ declare const _default: {
|
|
|
181
186
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
182
187
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
183
188
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
189
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
184
190
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
185
191
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
186
192
|
};
|
|
@@ -217,6 +223,7 @@ declare const _default: {
|
|
|
217
223
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
218
224
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
219
225
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
226
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
220
227
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
221
228
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
222
229
|
};
|
|
@@ -253,6 +260,7 @@ declare const _default: {
|
|
|
253
260
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
254
261
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
255
262
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
263
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
256
264
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
257
265
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
258
266
|
};
|
|
@@ -289,6 +297,7 @@ declare const _default: {
|
|
|
289
297
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
290
298
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
291
299
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
300
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
292
301
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
293
302
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
294
303
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ type Options$3 = [{
|
|
|
27
27
|
|
|
28
28
|
type Options$2 = [{
|
|
29
29
|
autofix?: boolean;
|
|
30
|
+
writablePrefixes?: string[];
|
|
30
31
|
}];
|
|
31
32
|
|
|
32
33
|
type Options$1 = [{
|
|
@@ -57,6 +58,7 @@ declare const plugin: {
|
|
|
57
58
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
58
59
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
59
60
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
61
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
60
62
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
61
63
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
62
64
|
};
|
|
@@ -82,6 +84,7 @@ declare const _default: {
|
|
|
82
84
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
83
85
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
84
86
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
87
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
85
88
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
86
89
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
87
90
|
};
|
|
@@ -109,6 +112,7 @@ declare const _default: {
|
|
|
109
112
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
110
113
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
111
114
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
115
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
112
116
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
113
117
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
114
118
|
};
|
|
@@ -145,6 +149,7 @@ declare const _default: {
|
|
|
145
149
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
146
150
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
147
151
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
152
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
148
153
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
149
154
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
150
155
|
};
|
|
@@ -181,6 +186,7 @@ declare const _default: {
|
|
|
181
186
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
182
187
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
183
188
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
189
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
184
190
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
185
191
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
186
192
|
};
|
|
@@ -217,6 +223,7 @@ declare const _default: {
|
|
|
217
223
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
218
224
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
219
225
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
226
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
220
227
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
221
228
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
222
229
|
};
|
|
@@ -253,6 +260,7 @@ declare const _default: {
|
|
|
253
260
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
254
261
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
255
262
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
263
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
256
264
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
257
265
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
258
266
|
};
|
|
@@ -289,6 +297,7 @@ declare const _default: {
|
|
|
289
297
|
'no-deprecated-props': PluginRuleModule<[]>;
|
|
290
298
|
'no-dot-ts-imports': PluginRuleModule<[]>;
|
|
291
299
|
'no-legacy-library-import': PluginRuleModule<[]>;
|
|
300
|
+
'no-redundant-flex-row': PluginRuleModule<[]>;
|
|
292
301
|
'no-unused-i18n-keys': PluginRuleModule<Options$6>;
|
|
293
302
|
'require-jsdoc-on-composable-options': PluginRuleModule<[]>;
|
|
294
303
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
-
import * as compat from 'eslint-compat-utils';
|
|
3
2
|
import debugFactory from 'debug';
|
|
4
3
|
import { extname, resolve } from 'node:path';
|
|
5
4
|
import { pascalCase, kebabCase } from 'scule';
|
|
@@ -7,32 +6,35 @@ import { statSync, readFileSync } from 'node:fs';
|
|
|
7
6
|
import { globSync } from 'tinyglobby';
|
|
8
7
|
import { parse } from 'vue-eslint-parser';
|
|
9
8
|
|
|
10
|
-
const version = "1.
|
|
9
|
+
const version = "1.4.0";
|
|
11
10
|
const pkg = {
|
|
12
11
|
version: version};
|
|
13
12
|
|
|
14
13
|
function getFilename(context) {
|
|
15
|
-
return
|
|
14
|
+
return context.filename;
|
|
16
15
|
}
|
|
17
16
|
function getSourceCode(context) {
|
|
18
|
-
return
|
|
17
|
+
return context.sourceCode;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
const COMPOSABLE_PATTERN = /^use[A-Z]/;
|
|
22
21
|
function isComposableName(name) {
|
|
23
22
|
return COMPOSABLE_PATTERN.test(name);
|
|
24
23
|
}
|
|
24
|
+
function isComposableNode(node) {
|
|
25
|
+
if (node.type === AST_NODE_TYPES.FunctionDeclaration)
|
|
26
|
+
return !!node.id && isComposableName(node.id.name);
|
|
27
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression || node.type === AST_NODE_TYPES.FunctionExpression) {
|
|
28
|
+
const parent = node.parent;
|
|
29
|
+
return parent?.type === AST_NODE_TYPES.VariableDeclarator && parent.id.type === AST_NODE_TYPES.Identifier && isComposableName(parent.id.name);
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
25
33
|
function getEnclosingComposable(node) {
|
|
26
34
|
let current = node.parent;
|
|
27
35
|
while (current) {
|
|
28
|
-
if (
|
|
36
|
+
if (isComposableNode(current))
|
|
29
37
|
return current;
|
|
30
|
-
if (current.type === AST_NODE_TYPES.ArrowFunctionExpression || current.type === AST_NODE_TYPES.FunctionExpression) {
|
|
31
|
-
const parent = current.parent;
|
|
32
|
-
if (parent?.type === AST_NODE_TYPES.VariableDeclarator && parent.id.type === AST_NODE_TYPES.Identifier && isComposableName(parent.id.name)) {
|
|
33
|
-
return current;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
38
|
current = current.parent;
|
|
37
39
|
}
|
|
38
40
|
return void 0;
|
|
@@ -64,22 +66,18 @@ function createRecommended(plugin, name, flat) {
|
|
|
64
66
|
return createConfig(plugin, name, flat, "recommended");
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
function getLiteralValue(node, stringOnly) {
|
|
70
|
+
if (node.value == null)
|
|
71
|
+
return !stringOnly && node.bigint != null ? node.bigint : null;
|
|
72
|
+
if (typeof node.value === "string")
|
|
73
|
+
return node.value;
|
|
74
|
+
return stringOnly ? null : String(node.value);
|
|
75
|
+
}
|
|
67
76
|
function getStringLiteralValue(node, stringOnly = false) {
|
|
68
|
-
if (node.type === "Literal")
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return node.bigint;
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
if (typeof node.value === "string")
|
|
75
|
-
return node.value;
|
|
76
|
-
if (!stringOnly)
|
|
77
|
-
return String(node.value);
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) {
|
|
77
|
+
if (node.type === "Literal")
|
|
78
|
+
return getLiteralValue(node, stringOnly);
|
|
79
|
+
if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1)
|
|
81
80
|
return node.quasis[0].value.cooked;
|
|
82
|
-
}
|
|
83
81
|
return null;
|
|
84
82
|
}
|
|
85
83
|
function getStaticPropertyName(node) {
|
|
@@ -166,7 +164,7 @@ function defineTemplateBodyVisitor(context, templateBodyVisitor, scriptVisitor,
|
|
|
166
164
|
);
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
const RULE_NAME$
|
|
167
|
+
const RULE_NAME$g = "composable-input-flexibility";
|
|
170
168
|
function checkParamForRef(param) {
|
|
171
169
|
let annotation;
|
|
172
170
|
if (param.type === AST_NODE_TYPES.Identifier && param.typeAnnotation) {
|
|
@@ -247,10 +245,10 @@ const composableInputFlexibility = createEslintRule({
|
|
|
247
245
|
],
|
|
248
246
|
type: "suggestion"
|
|
249
247
|
},
|
|
250
|
-
name: RULE_NAME$
|
|
248
|
+
name: RULE_NAME$g
|
|
251
249
|
});
|
|
252
250
|
|
|
253
|
-
const RULE_NAME$
|
|
251
|
+
const RULE_NAME$f = "composable-naming-convention";
|
|
254
252
|
function getComposableFunction(node) {
|
|
255
253
|
if (node.type === AST_NODE_TYPES.FunctionDeclaration) {
|
|
256
254
|
if (!node.id || !isComposableName(node.id.name))
|
|
@@ -279,6 +277,9 @@ const composableNamingConvention = createEslintRule({
|
|
|
279
277
|
checkComposable(node);
|
|
280
278
|
}
|
|
281
279
|
};
|
|
280
|
+
function isMismatchedConvention(typeName, prefix, suffix, expected) {
|
|
281
|
+
return !!typeName && typeName.startsWith(prefix) && typeName.endsWith(suffix) && typeName !== expected;
|
|
282
|
+
}
|
|
282
283
|
function checkComposable(node) {
|
|
283
284
|
const info = getComposableFunction(node);
|
|
284
285
|
if (!info)
|
|
@@ -288,26 +289,14 @@ const composableNamingConvention = createEslintRule({
|
|
|
288
289
|
const expectedReturn = `Use${pascalName}Return`;
|
|
289
290
|
for (const param of info.params) {
|
|
290
291
|
const annotation = getParamTypeAnnotation(param);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if (typeName && typeName.startsWith("Use") && typeName.endsWith("Options") && typeName !== expectedOptions) {
|
|
295
|
-
context.report({
|
|
296
|
-
data: { expected: expectedOptions, got: typeName },
|
|
297
|
-
messageId: "optionsNaming",
|
|
298
|
-
node: param
|
|
299
|
-
});
|
|
300
|
-
}
|
|
292
|
+
const typeName = annotation ? getTypeReferenceName(annotation) : void 0;
|
|
293
|
+
if (isMismatchedConvention(typeName, "Use", "Options", expectedOptions))
|
|
294
|
+
context.report({ data: { expected: expectedOptions, got: typeName }, messageId: "optionsNaming", node: param });
|
|
301
295
|
}
|
|
302
296
|
if (info.returnType) {
|
|
303
297
|
const returnTypeName = getTypeReferenceName(info.returnType.typeAnnotation);
|
|
304
|
-
if (returnTypeName
|
|
305
|
-
context.report({
|
|
306
|
-
data: { expected: expectedReturn, got: returnTypeName },
|
|
307
|
-
messageId: "returnNaming",
|
|
308
|
-
node: info.returnType
|
|
309
|
-
});
|
|
310
|
-
}
|
|
298
|
+
if (isMismatchedConvention(returnTypeName, "Use", "Return", expectedReturn))
|
|
299
|
+
context.report({ data: { expected: expectedReturn, got: returnTypeName }, messageId: "returnNaming", node: info.returnType });
|
|
311
300
|
}
|
|
312
301
|
}
|
|
313
302
|
function getParamTypeAnnotation(param) {
|
|
@@ -332,10 +321,10 @@ const composableNamingConvention = createEslintRule({
|
|
|
332
321
|
schema: [],
|
|
333
322
|
type: "suggestion"
|
|
334
323
|
},
|
|
335
|
-
name: RULE_NAME$
|
|
324
|
+
name: RULE_NAME$f
|
|
336
325
|
});
|
|
337
326
|
|
|
338
|
-
const RULE_NAME$
|
|
327
|
+
const RULE_NAME$e = "composable-no-default-export";
|
|
339
328
|
const composableNoDefaultExport = createEslintRule({
|
|
340
329
|
create(context) {
|
|
341
330
|
let hasComposable = false;
|
|
@@ -375,10 +364,10 @@ const composableNoDefaultExport = createEslintRule({
|
|
|
375
364
|
schema: [],
|
|
376
365
|
type: "problem"
|
|
377
366
|
},
|
|
378
|
-
name: RULE_NAME$
|
|
367
|
+
name: RULE_NAME$e
|
|
379
368
|
});
|
|
380
369
|
|
|
381
|
-
const RULE_NAME$
|
|
370
|
+
const RULE_NAME$d = "composable-prefer-shallowref";
|
|
382
371
|
const composablePreferShallowref = createEslintRule({
|
|
383
372
|
create(context) {
|
|
384
373
|
const autofix = context.options[0]?.autofix ?? false;
|
|
@@ -437,10 +426,10 @@ const composablePreferShallowref = createEslintRule({
|
|
|
437
426
|
],
|
|
438
427
|
type: "suggestion"
|
|
439
428
|
},
|
|
440
|
-
name: RULE_NAME$
|
|
429
|
+
name: RULE_NAME$d
|
|
441
430
|
});
|
|
442
431
|
|
|
443
|
-
const RULE_NAME$
|
|
432
|
+
const RULE_NAME$c = "composable-require-cleanup";
|
|
444
433
|
const SIDE_EFFECT_CALLS = /* @__PURE__ */ new Set(["addEventListener", "setInterval", "setTimeout"]);
|
|
445
434
|
const SIDE_EFFECT_CONSTRUCTORS = /* @__PURE__ */ new Set(["MutationObserver", "ResizeObserver", "IntersectionObserver"]);
|
|
446
435
|
const CLEANUP_HOOKS = /* @__PURE__ */ new Set(["onUnmounted", "onBeforeUnmount", "onScopeDispose", "tryOnScopeDispose"]);
|
|
@@ -534,16 +523,62 @@ const composableRequireCleanup = createEslintRule({
|
|
|
534
523
|
schema: [],
|
|
535
524
|
type: "problem"
|
|
536
525
|
},
|
|
537
|
-
name: RULE_NAME$
|
|
526
|
+
name: RULE_NAME$c
|
|
538
527
|
});
|
|
539
528
|
|
|
540
|
-
const RULE_NAME$
|
|
541
|
-
const
|
|
529
|
+
const RULE_NAME$b = "composable-return-readonly";
|
|
530
|
+
const DEFAULT_WRITABLE_PREFIXES = ["model"];
|
|
531
|
+
const REACTIVE_CREATORS = /* @__PURE__ */ new Set(["ref", "shallowRef"]);
|
|
532
|
+
const READONLY_CREATORS = /* @__PURE__ */ new Set(["computed"]);
|
|
533
|
+
function isReadonlyCall(node) {
|
|
534
|
+
return node.type === AST_NODE_TYPES.CallExpression && node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "readonly" && node.arguments.length === 1 && node.arguments[0].type === AST_NODE_TYPES.Identifier;
|
|
535
|
+
}
|
|
542
536
|
const composableReturnReadonly = createEslintRule({
|
|
543
537
|
create(context) {
|
|
544
538
|
const autofix = context.options[0]?.autofix ?? false;
|
|
539
|
+
const writablePrefixes = context.options[0]?.writablePrefixes ?? DEFAULT_WRITABLE_PREFIXES;
|
|
545
540
|
const source = getSourceCode(context);
|
|
546
541
|
const reactiveVars = /* @__PURE__ */ new Set();
|
|
542
|
+
const readonlyVars = /* @__PURE__ */ new Set();
|
|
543
|
+
function isWritableByConvention(name) {
|
|
544
|
+
return writablePrefixes.some((prefix) => {
|
|
545
|
+
if (!name.startsWith(prefix))
|
|
546
|
+
return false;
|
|
547
|
+
const next = name[prefix.length];
|
|
548
|
+
return next === void 0 || next >= "A" && next <= "Z";
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function reportWithFixOrSuggest(prop, name, messageId, suggestMessageId, fixFn) {
|
|
552
|
+
context.report({
|
|
553
|
+
data: { name },
|
|
554
|
+
...autofix ? { fix: fixFn } : { suggest: [{ data: { name }, fix: fixFn, messageId: suggestMessageId }] },
|
|
555
|
+
messageId,
|
|
556
|
+
node: prop
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
function checkUnnecessaryReadonly(prop) {
|
|
560
|
+
const valueNode = prop.shorthand ? null : prop.value;
|
|
561
|
+
if (!valueNode || !isReadonlyCall(valueNode))
|
|
562
|
+
return false;
|
|
563
|
+
const innerName = valueNode.arguments[0].name;
|
|
564
|
+
if (!readonlyVars.has(innerName))
|
|
565
|
+
return false;
|
|
566
|
+
reportWithFixOrSuggest(prop, innerName, "unnecessaryReadonly", "suggestRemoveReadonly", (fixer) => fixer.replaceText(valueNode, innerName));
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
function checkMissingReadonly(prop) {
|
|
570
|
+
if (prop.shorthand && prop.key.type === AST_NODE_TYPES.Identifier && reactiveVars.has(prop.key.name)) {
|
|
571
|
+
const keyName = prop.key.name;
|
|
572
|
+
if (isWritableByConvention(keyName))
|
|
573
|
+
return;
|
|
574
|
+
reportWithFixOrSuggest(prop, keyName, "wrapReadonly", "suggestWrapReadonly", (fixer) => fixer.replaceText(prop, `${keyName}: readonly(${keyName})`));
|
|
575
|
+
} else if (!prop.shorthand && prop.value.type === AST_NODE_TYPES.Identifier && reactiveVars.has(prop.value.name)) {
|
|
576
|
+
const valueName = prop.value.name;
|
|
577
|
+
if (isWritableByConvention(valueName))
|
|
578
|
+
return;
|
|
579
|
+
reportWithFixOrSuggest(prop, valueName, "wrapReadonly", "suggestWrapReadonly", (fixer) => fixer.replaceText(prop.value, `readonly(${prop.value.type === AST_NODE_TYPES.Identifier ? prop.value.name : source.getText(prop.value)})`));
|
|
580
|
+
}
|
|
581
|
+
}
|
|
547
582
|
return {
|
|
548
583
|
ReturnStatement: (node) => {
|
|
549
584
|
if (!getEnclosingComposable(node))
|
|
@@ -553,25 +588,8 @@ const composableReturnReadonly = createEslintRule({
|
|
|
553
588
|
for (const prop of node.argument.properties) {
|
|
554
589
|
if (prop.type !== AST_NODE_TYPES.Property)
|
|
555
590
|
continue;
|
|
556
|
-
if (
|
|
557
|
-
|
|
558
|
-
const fixFn = (fixer) => fixer.replaceText(prop, `${keyName}: readonly(${keyName})`);
|
|
559
|
-
context.report({
|
|
560
|
-
data: { name: keyName },
|
|
561
|
-
...autofix ? { fix: fixFn } : { suggest: [{ data: { name: keyName }, fix: fixFn, messageId: "suggestWrapReadonly" }] },
|
|
562
|
-
messageId: "wrapReadonly",
|
|
563
|
-
node: prop
|
|
564
|
-
});
|
|
565
|
-
} else if (!prop.shorthand && prop.value.type === AST_NODE_TYPES.Identifier && reactiveVars.has(prop.value.name)) {
|
|
566
|
-
const valueName = prop.value.name;
|
|
567
|
-
const fixFn = (fixer) => fixer.replaceText(prop.value, `readonly(${prop.value.type === AST_NODE_TYPES.Identifier ? prop.value.name : source.getText(prop.value)})`);
|
|
568
|
-
context.report({
|
|
569
|
-
data: { name: valueName },
|
|
570
|
-
...autofix ? { fix: fixFn } : { suggest: [{ data: { name: valueName }, fix: fixFn, messageId: "suggestWrapReadonly" }] },
|
|
571
|
-
messageId: "wrapReadonly",
|
|
572
|
-
node: prop
|
|
573
|
-
});
|
|
574
|
-
}
|
|
591
|
+
if (!checkUnnecessaryReadonly(prop))
|
|
592
|
+
checkMissingReadonly(prop);
|
|
575
593
|
}
|
|
576
594
|
},
|
|
577
595
|
VariableDeclarator: (node) => {
|
|
@@ -579,13 +597,18 @@ const composableReturnReadonly = createEslintRule({
|
|
|
579
597
|
return;
|
|
580
598
|
if (node.id.type !== AST_NODE_TYPES.Identifier)
|
|
581
599
|
return;
|
|
582
|
-
if (node.init?.type === AST_NODE_TYPES.CallExpression && node.init.callee.type === AST_NODE_TYPES.Identifier
|
|
583
|
-
|
|
600
|
+
if (node.init?.type === AST_NODE_TYPES.CallExpression && node.init.callee.type === AST_NODE_TYPES.Identifier) {
|
|
601
|
+
const calleeName = node.init.callee.name;
|
|
602
|
+
if (REACTIVE_CREATORS.has(calleeName)) {
|
|
603
|
+
reactiveVars.add(node.id.name);
|
|
604
|
+
} else if (READONLY_CREATORS.has(calleeName)) {
|
|
605
|
+
readonlyVars.add(node.id.name);
|
|
606
|
+
}
|
|
584
607
|
}
|
|
585
608
|
}
|
|
586
609
|
};
|
|
587
610
|
},
|
|
588
|
-
defaultOptions: [{ autofix: false }],
|
|
611
|
+
defaultOptions: [{ autofix: false, writablePrefixes: DEFAULT_WRITABLE_PREFIXES }],
|
|
589
612
|
meta: {
|
|
590
613
|
docs: {
|
|
591
614
|
description: "Require returned refs from composables to be wrapped with readonly()",
|
|
@@ -594,7 +617,9 @@ const composableReturnReadonly = createEslintRule({
|
|
|
594
617
|
fixable: "code",
|
|
595
618
|
hasSuggestions: true,
|
|
596
619
|
messages: {
|
|
620
|
+
suggestRemoveReadonly: "Remove unnecessary readonly() from '{{ name }}'.",
|
|
597
621
|
suggestWrapReadonly: "Wrap '{{ name }}' with readonly().",
|
|
622
|
+
unnecessaryReadonly: "Computed ref '{{ name }}' is already readonly and does not need readonly() wrapping.",
|
|
598
623
|
wrapReadonly: "Returned ref '{{ name }}' should be wrapped with readonly()."
|
|
599
624
|
},
|
|
600
625
|
schema: [
|
|
@@ -605,6 +630,12 @@ const composableReturnReadonly = createEslintRule({
|
|
|
605
630
|
default: false,
|
|
606
631
|
description: "Enable auto-fix. When disabled, the fix is available as a suggestion.",
|
|
607
632
|
type: "boolean"
|
|
633
|
+
},
|
|
634
|
+
writablePrefixes: {
|
|
635
|
+
default: DEFAULT_WRITABLE_PREFIXES,
|
|
636
|
+
description: "Returned variables whose name starts with one of these prefixes are exempt from the readonly() requirement (e.g. refs intended for v-model binding).",
|
|
637
|
+
items: { type: "string" },
|
|
638
|
+
type: "array"
|
|
608
639
|
}
|
|
609
640
|
},
|
|
610
641
|
type: "object"
|
|
@@ -612,10 +643,10 @@ const composableReturnReadonly = createEslintRule({
|
|
|
612
643
|
],
|
|
613
644
|
type: "suggestion"
|
|
614
645
|
},
|
|
615
|
-
name: RULE_NAME$
|
|
646
|
+
name: RULE_NAME$b
|
|
616
647
|
});
|
|
617
648
|
|
|
618
|
-
const RULE_NAME$
|
|
649
|
+
const RULE_NAME$a = "composable-ssr-safety";
|
|
619
650
|
const BROWSER_GLOBALS = /* @__PURE__ */ new Set(["window", "document", "navigator"]);
|
|
620
651
|
const LIFECYCLE_HOOKS = /* @__PURE__ */ new Set(["onMounted", "onBeforeMount"]);
|
|
621
652
|
function isInsideLifecycleHook(node) {
|
|
@@ -642,15 +673,12 @@ function isInsideTypeofCheck(node) {
|
|
|
642
673
|
}
|
|
643
674
|
return false;
|
|
644
675
|
}
|
|
676
|
+
function isTypeofBrowserGlobal(node) {
|
|
677
|
+
return node.type === AST_NODE_TYPES.UnaryExpression && node.operator === "typeof" && node.argument.type === AST_NODE_TYPES.Identifier && BROWSER_GLOBALS.has(node.argument.name);
|
|
678
|
+
}
|
|
645
679
|
function hasTypeofCheck(node) {
|
|
646
|
-
if (node.type === AST_NODE_TYPES.BinaryExpression)
|
|
647
|
-
|
|
648
|
-
return true;
|
|
649
|
-
}
|
|
650
|
-
if (node.right.type === AST_NODE_TYPES.UnaryExpression && node.right.operator === "typeof" && node.right.argument.type === AST_NODE_TYPES.Identifier && BROWSER_GLOBALS.has(node.right.argument.name)) {
|
|
651
|
-
return true;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
680
|
+
if (node.type === AST_NODE_TYPES.BinaryExpression)
|
|
681
|
+
return isTypeofBrowserGlobal(node.left) || isTypeofBrowserGlobal(node.right);
|
|
654
682
|
if (node.type === AST_NODE_TYPES.LogicalExpression)
|
|
655
683
|
return hasTypeofCheck(node.left) || hasTypeofCheck(node.right);
|
|
656
684
|
return false;
|
|
@@ -706,56 +734,51 @@ const composableSsrSafety = createEslintRule({
|
|
|
706
734
|
schema: [],
|
|
707
735
|
type: "problem"
|
|
708
736
|
},
|
|
709
|
-
name: RULE_NAME$
|
|
737
|
+
name: RULE_NAME$a
|
|
710
738
|
});
|
|
711
739
|
|
|
712
740
|
const debug$6 = debugFactory("@rotki/eslint-plugin:consistent-ref-type-annotation");
|
|
713
|
-
const RULE_NAME$
|
|
741
|
+
const RULE_NAME$9 = "consistent-ref-type-annotation";
|
|
714
742
|
const FIXABLE_METHODS = /* @__PURE__ */ new Set(["ref", "computed"]);
|
|
715
|
-
function
|
|
716
|
-
let declarationTypeArguments;
|
|
743
|
+
function getFixableCallExpression(declaration) {
|
|
717
744
|
const init = declaration.init;
|
|
718
|
-
if (!
|
|
719
|
-
return;
|
|
745
|
+
if (!init || init.type !== TSESTree.AST_NODE_TYPES.CallExpression)
|
|
746
|
+
return void 0;
|
|
720
747
|
const callee = init.callee;
|
|
721
|
-
if (!
|
|
722
|
-
return;
|
|
723
|
-
|
|
748
|
+
if (!callee || callee.type !== TSESTree.AST_NODE_TYPES.Identifier || !FIXABLE_METHODS.has(callee.name))
|
|
749
|
+
return void 0;
|
|
750
|
+
return { callee, init };
|
|
751
|
+
}
|
|
752
|
+
function getDeclarationTypeArguments(declaration) {
|
|
753
|
+
const typeNode = declaration.id.typeAnnotation?.typeAnnotation;
|
|
754
|
+
if (typeNode?.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
|
|
755
|
+
return typeNode.typeArguments;
|
|
756
|
+
return void 0;
|
|
757
|
+
}
|
|
758
|
+
function checkAssignmentDeclaration(context, source, node, declaration, allowInference) {
|
|
759
|
+
const call = getFixableCallExpression(declaration);
|
|
760
|
+
if (!call)
|
|
724
761
|
return;
|
|
762
|
+
const { callee, init } = call;
|
|
725
763
|
const name = callee.name;
|
|
726
764
|
debug$6(`found ${name}, checking type arguments`);
|
|
727
|
-
const
|
|
765
|
+
const initTypeArgs = init.typeArguments;
|
|
766
|
+
const declTypeArgs = getDeclarationTypeArguments(declaration);
|
|
728
767
|
const typeAnnotation = declaration.id.typeAnnotation;
|
|
729
|
-
if (
|
|
730
|
-
const typeNode = typeAnnotation.typeAnnotation;
|
|
731
|
-
if (typeNode && typeNode.type === TSESTree.AST_NODE_TYPES.TSTypeReference)
|
|
732
|
-
declarationTypeArguments = typeNode.typeArguments;
|
|
733
|
-
}
|
|
734
|
-
if (initializationTypeArguments && !declarationTypeArguments)
|
|
768
|
+
if (initTypeArgs && !declTypeArgs)
|
|
735
769
|
return;
|
|
736
770
|
debug$6(`generating report for ${name}`);
|
|
737
|
-
if (!
|
|
738
|
-
if (allowInference)
|
|
739
|
-
|
|
740
|
-
} else {
|
|
741
|
-
context.report({
|
|
742
|
-
data: {
|
|
743
|
-
name
|
|
744
|
-
},
|
|
745
|
-
messageId: "missingType",
|
|
746
|
-
node
|
|
747
|
-
});
|
|
748
|
-
}
|
|
771
|
+
if (!initTypeArgs && !declTypeArgs) {
|
|
772
|
+
if (!allowInference)
|
|
773
|
+
context.report({ data: { name }, messageId: "missingType", node });
|
|
749
774
|
return;
|
|
750
775
|
}
|
|
751
776
|
context.report({
|
|
752
|
-
data: {
|
|
753
|
-
name
|
|
754
|
-
},
|
|
777
|
+
data: { name },
|
|
755
778
|
fix(fixer) {
|
|
756
779
|
const fixes = [];
|
|
757
|
-
if (!
|
|
758
|
-
fixes.push(fixer.insertTextAfter(callee, source.getText(
|
|
780
|
+
if (!initTypeArgs && callee)
|
|
781
|
+
fixes.push(fixer.insertTextAfter(callee, source.getText(declTypeArgs)));
|
|
759
782
|
if (typeAnnotation)
|
|
760
783
|
fixes.push(fixer.remove(typeAnnotation));
|
|
761
784
|
return fixes;
|
|
@@ -804,10 +827,10 @@ const consistentRefTypeAnnotation = createEslintRule({
|
|
|
804
827
|
],
|
|
805
828
|
type: "problem"
|
|
806
829
|
},
|
|
807
|
-
name: RULE_NAME$
|
|
830
|
+
name: RULE_NAME$9
|
|
808
831
|
});
|
|
809
832
|
|
|
810
|
-
const RULE_NAME$
|
|
833
|
+
const RULE_NAME$8 = "max-dependencies";
|
|
811
834
|
const maxDependencies = createEslintRule({
|
|
812
835
|
create(context, [options]) {
|
|
813
836
|
let dependencyCount = 0;
|
|
@@ -867,10 +890,10 @@ const maxDependencies = createEslintRule({
|
|
|
867
890
|
],
|
|
868
891
|
type: "suggestion"
|
|
869
892
|
},
|
|
870
|
-
name: RULE_NAME$
|
|
893
|
+
name: RULE_NAME$8
|
|
871
894
|
});
|
|
872
895
|
|
|
873
|
-
const RULE_NAME$
|
|
896
|
+
const RULE_NAME$7 = "no-deprecated-classes";
|
|
874
897
|
const debug$5 = debugFactory("@rotki/eslint-plugin:no-deprecated-classes");
|
|
875
898
|
const stringReplacements = /* @__PURE__ */ new Map([
|
|
876
899
|
["d-block", "block"],
|
|
@@ -947,51 +970,62 @@ function reportReplacement(className, replacement, node, context, source, positi
|
|
|
947
970
|
messageId: "replacedWith"
|
|
948
971
|
});
|
|
949
972
|
}
|
|
973
|
+
function splitClassNames(classNames, reportNode) {
|
|
974
|
+
return classNames.split(/\s+/).map((className) => ({ className, position: classNames.indexOf(className) + 1, reportNode }));
|
|
975
|
+
}
|
|
976
|
+
function* extractFromObject(node) {
|
|
977
|
+
for (const prop of node.properties) {
|
|
978
|
+
if (prop.type !== "Property")
|
|
979
|
+
continue;
|
|
980
|
+
const classNames = getStaticPropertyName(prop);
|
|
981
|
+
if (classNames)
|
|
982
|
+
yield* splitClassNames(classNames, prop.key);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
function* extractFromArray(node) {
|
|
986
|
+
for (const element of node.elements) {
|
|
987
|
+
if (element == null || element.type === "SpreadElement")
|
|
988
|
+
continue;
|
|
989
|
+
yield* extractClassNames(element);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
function* extractFromTemplateLiteral(node) {
|
|
993
|
+
for (const templateElement of node.quasis) {
|
|
994
|
+
const classNames = templateElement.value.cooked;
|
|
995
|
+
if (classNames !== null)
|
|
996
|
+
yield* splitClassNames(classNames, templateElement);
|
|
997
|
+
}
|
|
998
|
+
for (const expr of node.expressions)
|
|
999
|
+
yield* extractClassNames(expr, true);
|
|
1000
|
+
}
|
|
1001
|
+
function* extractFromBinary(node) {
|
|
1002
|
+
if (node.operator !== "+")
|
|
1003
|
+
return;
|
|
1004
|
+
if (node.left.type !== "PrivateIdentifier")
|
|
1005
|
+
yield* extractClassNames(node.left, true);
|
|
1006
|
+
yield* extractClassNames(node.right, true);
|
|
1007
|
+
}
|
|
950
1008
|
function* extractClassNames(node, textOnly = false) {
|
|
951
1009
|
if (node.type === "Literal") {
|
|
952
|
-
|
|
953
|
-
yield* classNames.split(/\s+/).map((className) => ({ className, position: classNames.indexOf(className) + 1, reportNode: node }));
|
|
1010
|
+
yield* splitClassNames(`${node.value}`, node);
|
|
954
1011
|
return;
|
|
955
1012
|
}
|
|
956
1013
|
if (node.type === "TemplateLiteral") {
|
|
957
|
-
|
|
958
|
-
const classNames = templateElement.value.cooked;
|
|
959
|
-
if (classNames === null)
|
|
960
|
-
continue;
|
|
961
|
-
yield* classNames.split(/\s+/).map((className) => ({ className, position: classNames.indexOf(className) + 1, reportNode: templateElement }));
|
|
962
|
-
}
|
|
963
|
-
for (const expr of node.expressions)
|
|
964
|
-
yield* extractClassNames(expr, true);
|
|
1014
|
+
yield* extractFromTemplateLiteral(node);
|
|
965
1015
|
return;
|
|
966
1016
|
}
|
|
967
1017
|
if (node.type === "BinaryExpression") {
|
|
968
|
-
|
|
969
|
-
return;
|
|
970
|
-
yield* extractClassNames(node.left, true);
|
|
971
|
-
yield* extractClassNames(node.right, true);
|
|
1018
|
+
yield* extractFromBinary(node);
|
|
972
1019
|
return;
|
|
973
1020
|
}
|
|
974
1021
|
if (textOnly)
|
|
975
1022
|
return;
|
|
976
1023
|
if (node.type === "ObjectExpression") {
|
|
977
|
-
|
|
978
|
-
if (prop.type !== "Property")
|
|
979
|
-
continue;
|
|
980
|
-
const classNames = getStaticPropertyName(prop);
|
|
981
|
-
if (!classNames)
|
|
982
|
-
continue;
|
|
983
|
-
yield* classNames.split(/\s+/).map((className) => ({ className, position: classNames.indexOf(className) + 1, reportNode: prop.key }));
|
|
984
|
-
}
|
|
1024
|
+
yield* extractFromObject(node);
|
|
985
1025
|
return;
|
|
986
1026
|
}
|
|
987
1027
|
if (node.type === "ArrayExpression") {
|
|
988
|
-
|
|
989
|
-
if (element == null)
|
|
990
|
-
continue;
|
|
991
|
-
if (element.type === "SpreadElement")
|
|
992
|
-
continue;
|
|
993
|
-
yield* extractClassNames(element);
|
|
994
|
-
}
|
|
1028
|
+
yield* extractFromArray(node);
|
|
995
1029
|
}
|
|
996
1030
|
if (node.type === "ConditionalExpression") {
|
|
997
1031
|
yield* extractClassNames(node.consequent);
|
|
@@ -1038,11 +1072,11 @@ const noDeprecatedClasses = createEslintRule({
|
|
|
1038
1072
|
schema: [],
|
|
1039
1073
|
type: "problem"
|
|
1040
1074
|
},
|
|
1041
|
-
name: RULE_NAME$
|
|
1075
|
+
name: RULE_NAME$7
|
|
1042
1076
|
});
|
|
1043
1077
|
|
|
1044
1078
|
const debug$4 = debugFactory("@rotki/eslint-plugin:no-deprecated-components");
|
|
1045
|
-
const RULE_NAME$
|
|
1079
|
+
const RULE_NAME$6 = "no-deprecated-components";
|
|
1046
1080
|
const vuetify = {
|
|
1047
1081
|
VApp: true,
|
|
1048
1082
|
VAppBar: true,
|
|
@@ -1079,7 +1113,7 @@ const skipInLegacy = /* @__PURE__ */ new Set([
|
|
|
1079
1113
|
"Fragment"
|
|
1080
1114
|
]);
|
|
1081
1115
|
function hasReplacement$1(tag) {
|
|
1082
|
-
return Object.
|
|
1116
|
+
return Object.hasOwn(replacements$1, tag);
|
|
1083
1117
|
}
|
|
1084
1118
|
const noDeprecatedComponents = createEslintRule({
|
|
1085
1119
|
create(context, optionsWithDefault) {
|
|
@@ -1147,11 +1181,10 @@ const noDeprecatedComponents = createEslintRule({
|
|
|
1147
1181
|
],
|
|
1148
1182
|
type: "problem"
|
|
1149
1183
|
},
|
|
1150
|
-
name: RULE_NAME$
|
|
1184
|
+
name: RULE_NAME$6
|
|
1151
1185
|
});
|
|
1152
1186
|
|
|
1153
|
-
const
|
|
1154
|
-
const RULE_NAME$4 = "no-deprecated-props";
|
|
1187
|
+
const RULE_NAME$5 = "no-deprecated-props";
|
|
1155
1188
|
const replacements = {
|
|
1156
1189
|
RuiRadio: {
|
|
1157
1190
|
internalValue: "value"
|
|
@@ -1174,37 +1207,34 @@ function getPropName(node) {
|
|
|
1174
1207
|
}
|
|
1175
1208
|
return kebabCase(node.key.rawName);
|
|
1176
1209
|
}
|
|
1210
|
+
function isNonBindDirective(node) {
|
|
1211
|
+
return node.directive && node.value?.type === "VExpressionContainer" && (node.key.name.name !== "bind" || !node.key.argument);
|
|
1212
|
+
}
|
|
1213
|
+
function getPropNameNode(node) {
|
|
1214
|
+
return node.directive ? node.key.argument : node.key;
|
|
1215
|
+
}
|
|
1177
1216
|
const noDeprecatedProps = createEslintRule({
|
|
1178
1217
|
create(context) {
|
|
1179
1218
|
return defineTemplateBodyVisitor(context, {
|
|
1180
1219
|
VAttribute(node) {
|
|
1181
|
-
if (
|
|
1220
|
+
if (isNonBindDirective(node))
|
|
1182
1221
|
return;
|
|
1183
1222
|
const tag = pascalCase(node.parent.parent.rawName);
|
|
1184
1223
|
if (!hasReplacement(tag))
|
|
1185
1224
|
return;
|
|
1186
|
-
debug$3(`${tag} has replacement properties`);
|
|
1187
1225
|
const propName = getPropName(node);
|
|
1188
|
-
const propNameNode = node
|
|
1189
|
-
if (!propName || !propNameNode)
|
|
1190
|
-
debug$3("could not get prop name and/or node");
|
|
1226
|
+
const propNameNode = getPropNameNode(node);
|
|
1227
|
+
if (!propName || !propNameNode)
|
|
1191
1228
|
return;
|
|
1192
|
-
}
|
|
1193
1229
|
const match = replacementMaps.get(tag)?.get(propName);
|
|
1194
|
-
if (match)
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
return fixer.replaceText(propNameNode, match.replacement);
|
|
1203
|
-
},
|
|
1204
|
-
messageId: "replacedWith",
|
|
1205
|
-
node: propNameNode
|
|
1206
|
-
});
|
|
1207
|
-
}
|
|
1230
|
+
if (!match)
|
|
1231
|
+
return;
|
|
1232
|
+
context.report({
|
|
1233
|
+
data: { prop: match.original, replacement: match.replacement },
|
|
1234
|
+
fix: (fixer) => fixer.replaceText(propNameNode, match.replacement),
|
|
1235
|
+
messageId: "replacedWith",
|
|
1236
|
+
node: propNameNode
|
|
1237
|
+
});
|
|
1208
1238
|
}
|
|
1209
1239
|
});
|
|
1210
1240
|
},
|
|
@@ -1221,10 +1251,10 @@ const noDeprecatedProps = createEslintRule({
|
|
|
1221
1251
|
schema: [],
|
|
1222
1252
|
type: "problem"
|
|
1223
1253
|
},
|
|
1224
|
-
name: RULE_NAME$
|
|
1254
|
+
name: RULE_NAME$5
|
|
1225
1255
|
});
|
|
1226
1256
|
|
|
1227
|
-
const RULE_NAME$
|
|
1257
|
+
const RULE_NAME$4 = "no-dot-ts-imports";
|
|
1228
1258
|
const noDotTsImport = createEslintRule({
|
|
1229
1259
|
create(context) {
|
|
1230
1260
|
return {
|
|
@@ -1259,10 +1289,10 @@ const noDotTsImport = createEslintRule({
|
|
|
1259
1289
|
schema: [],
|
|
1260
1290
|
type: "problem"
|
|
1261
1291
|
},
|
|
1262
|
-
name: RULE_NAME$
|
|
1292
|
+
name: RULE_NAME$4
|
|
1263
1293
|
});
|
|
1264
1294
|
|
|
1265
|
-
const RULE_NAME$
|
|
1295
|
+
const RULE_NAME$3 = "no-legacy-library-import";
|
|
1266
1296
|
const legacyLibrary = "@rotki/ui-library-compat";
|
|
1267
1297
|
const newLibrary = "@rotki/ui-library";
|
|
1268
1298
|
const noLegacyLibraryImport = createEslintRule({
|
|
@@ -1295,6 +1325,119 @@ const noLegacyLibraryImport = createEslintRule({
|
|
|
1295
1325
|
schema: [],
|
|
1296
1326
|
type: "problem"
|
|
1297
1327
|
},
|
|
1328
|
+
name: RULE_NAME$3
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
const RULE_NAME$2 = "no-redundant-flex-row";
|
|
1332
|
+
const debug$3 = debugFactory("@rotki/eslint-plugin:no-redundant-flex-row");
|
|
1333
|
+
function stripImportant(token) {
|
|
1334
|
+
return token.replace(/^!/, "").replace(/!$/, "");
|
|
1335
|
+
}
|
|
1336
|
+
function isUnconditional(token) {
|
|
1337
|
+
return !token.includes(":");
|
|
1338
|
+
}
|
|
1339
|
+
function isFlexDisplay(token) {
|
|
1340
|
+
if (!isUnconditional(token))
|
|
1341
|
+
return false;
|
|
1342
|
+
const base = stripImportant(token);
|
|
1343
|
+
return base === "flex" || base === "inline-flex";
|
|
1344
|
+
}
|
|
1345
|
+
function isFlexRow(token) {
|
|
1346
|
+
if (!isUnconditional(token))
|
|
1347
|
+
return false;
|
|
1348
|
+
return stripImportant(token) === "flex-row";
|
|
1349
|
+
}
|
|
1350
|
+
function tokenize(value) {
|
|
1351
|
+
const tokens = [];
|
|
1352
|
+
const matcher = /\S+/g;
|
|
1353
|
+
let match;
|
|
1354
|
+
while ((match = matcher.exec(value)) !== null)
|
|
1355
|
+
tokens.push({ start: match.index, text: match[0] });
|
|
1356
|
+
return tokens;
|
|
1357
|
+
}
|
|
1358
|
+
function removalRange(value, token, contentStart) {
|
|
1359
|
+
let startRel = token.start;
|
|
1360
|
+
let endRel = token.start + token.text.length;
|
|
1361
|
+
if (startRel > 0 && /\s/.test(value[startRel - 1])) {
|
|
1362
|
+
while (startRel > 0 && /\s/.test(value[startRel - 1]))
|
|
1363
|
+
startRel--;
|
|
1364
|
+
} else {
|
|
1365
|
+
while (endRel < value.length && /\s/.test(value[endRel]))
|
|
1366
|
+
endRel++;
|
|
1367
|
+
}
|
|
1368
|
+
return [contentStart + startRel, contentStart + endRel];
|
|
1369
|
+
}
|
|
1370
|
+
function reportRedundant(source, context, sourceCode) {
|
|
1371
|
+
const tokens = tokenize(source.value);
|
|
1372
|
+
if (!tokens.some((token) => isFlexDisplay(token.text)))
|
|
1373
|
+
return;
|
|
1374
|
+
for (const token of tokens) {
|
|
1375
|
+
if (!isFlexRow(token.text))
|
|
1376
|
+
continue;
|
|
1377
|
+
debug$3(`found redundant flex-row token '${token.text}'`);
|
|
1378
|
+
const tokenRange = [
|
|
1379
|
+
source.contentStart + token.start,
|
|
1380
|
+
source.contentStart + token.start + token.text.length
|
|
1381
|
+
];
|
|
1382
|
+
const removal = removalRange(source.value, token, source.contentStart);
|
|
1383
|
+
context.report({
|
|
1384
|
+
data: { className: token.text },
|
|
1385
|
+
fix(fixer) {
|
|
1386
|
+
return fixer.removeRange(removal);
|
|
1387
|
+
},
|
|
1388
|
+
loc: {
|
|
1389
|
+
end: sourceCode.getLocFromIndex(tokenRange[1]),
|
|
1390
|
+
start: sourceCode.getLocFromIndex(tokenRange[0])
|
|
1391
|
+
},
|
|
1392
|
+
messageId: "redundantFlexRow"
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
function plainStringLists(expression) {
|
|
1397
|
+
if (expression.type === "Literal" && typeof expression.value === "string")
|
|
1398
|
+
return [{ contentStart: expression.range[0] + 1, value: expression.value }];
|
|
1399
|
+
if (expression.type === "TemplateLiteral" && expression.expressions.length === 0 && expression.quasis.length === 1) {
|
|
1400
|
+
const quasi = expression.quasis[0];
|
|
1401
|
+
const cooked = quasi.value.cooked;
|
|
1402
|
+
if (cooked !== null)
|
|
1403
|
+
return [{ contentStart: quasi.range[0] + 1, value: cooked }];
|
|
1404
|
+
}
|
|
1405
|
+
return [];
|
|
1406
|
+
}
|
|
1407
|
+
const noRedundantFlexRow = createEslintRule({
|
|
1408
|
+
create(context) {
|
|
1409
|
+
const sourceCode = getSourceCode(context);
|
|
1410
|
+
return defineTemplateBodyVisitor(context, {
|
|
1411
|
+
'VAttribute[directive=false][key.name="class"]': function(node) {
|
|
1412
|
+
if (!node.value || !node.value.value || !node.value.range)
|
|
1413
|
+
return;
|
|
1414
|
+
reportRedundant(
|
|
1415
|
+
{ contentStart: node.value.range[0] + 1, value: node.value.value },
|
|
1416
|
+
context,
|
|
1417
|
+
sourceCode
|
|
1418
|
+
);
|
|
1419
|
+
},
|
|
1420
|
+
"VAttribute[directive=true][key.name.name='bind'][key.argument.name='class'] > VExpressionContainer.value": function(node) {
|
|
1421
|
+
if (!node.expression)
|
|
1422
|
+
return;
|
|
1423
|
+
for (const source of plainStringLists(node.expression))
|
|
1424
|
+
reportRedundant(source, context, sourceCode);
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
},
|
|
1428
|
+
defaultOptions: [],
|
|
1429
|
+
meta: {
|
|
1430
|
+
docs: {
|
|
1431
|
+
description: "disallow redundant `flex-row` since `flex` already defaults to the row direction",
|
|
1432
|
+
recommendation: "recommended"
|
|
1433
|
+
},
|
|
1434
|
+
fixable: "code",
|
|
1435
|
+
messages: {
|
|
1436
|
+
redundantFlexRow: `'{{ className }}' is redundant because 'flex' already lays out in the row direction; remove it, or keep it only behind a conditional variant (e.g. 'sm:flex-row')`
|
|
1437
|
+
},
|
|
1438
|
+
schema: [],
|
|
1439
|
+
type: "suggestion"
|
|
1440
|
+
},
|
|
1298
1441
|
name: RULE_NAME$2
|
|
1299
1442
|
});
|
|
1300
1443
|
|
|
@@ -1311,18 +1454,39 @@ function isI18nCallExpression(node) {
|
|
|
1311
1454
|
return I18N_FUNCTION_NAMES.has(callee.name);
|
|
1312
1455
|
return callee.type === "MemberExpression" && !callee.computed && isAstNode(callee.property) && callee.property.type === "Identifier" && typeof callee.property.name === "string" && I18N_MEMBER_NAMES.has(callee.property.name);
|
|
1313
1456
|
}
|
|
1314
|
-
function
|
|
1315
|
-
|
|
1316
|
-
const expressions = arg.expressions;
|
|
1317
|
-
if (!Array.isArray(quasis) || !Array.isArray(expressions) || quasis.length === 0)
|
|
1318
|
-
return void 0;
|
|
1319
|
-
const firstQuasi = quasis[0];
|
|
1320
|
-
if (!firstQuasi || typeof firstQuasi !== "object" || !("value" in firstQuasi))
|
|
1457
|
+
function getQuasiText(quasi) {
|
|
1458
|
+
if (!quasi || typeof quasi !== "object" || !("value" in quasi))
|
|
1321
1459
|
return void 0;
|
|
1322
|
-
const quasiObj =
|
|
1460
|
+
const quasiObj = quasi.value;
|
|
1323
1461
|
if (!quasiObj || typeof quasiObj !== "object")
|
|
1324
1462
|
return void 0;
|
|
1325
|
-
|
|
1463
|
+
if ("cooked" in quasiObj && typeof quasiObj.cooked === "string")
|
|
1464
|
+
return quasiObj.cooked;
|
|
1465
|
+
if ("raw" in quasiObj && typeof quasiObj.raw === "string")
|
|
1466
|
+
return quasiObj.raw;
|
|
1467
|
+
return void 0;
|
|
1468
|
+
}
|
|
1469
|
+
function getTemplateLiteralText(arg) {
|
|
1470
|
+
const { expressions, quasis } = arg;
|
|
1471
|
+
if (!Array.isArray(quasis) || !Array.isArray(expressions) || quasis.length === 0)
|
|
1472
|
+
return void 0;
|
|
1473
|
+
return getQuasiText(quasis[0]);
|
|
1474
|
+
}
|
|
1475
|
+
function isStaticTemplateLiteral(arg) {
|
|
1476
|
+
return Array.isArray(arg.expressions) && arg.expressions.length === 0 && Array.isArray(arg.quasis) && arg.quasis.length === 1;
|
|
1477
|
+
}
|
|
1478
|
+
function extractKeyFromArg(arg) {
|
|
1479
|
+
if (arg.type === "Literal" && typeof arg.value === "string")
|
|
1480
|
+
return arg.value;
|
|
1481
|
+
if (arg.type === "TemplateLiteral") {
|
|
1482
|
+
const text = getTemplateLiteralText(arg);
|
|
1483
|
+
if (text === void 0)
|
|
1484
|
+
return void 0;
|
|
1485
|
+
if (isStaticTemplateLiteral(arg))
|
|
1486
|
+
return text;
|
|
1487
|
+
return text ? `${text}*` : void 0;
|
|
1488
|
+
}
|
|
1489
|
+
return void 0;
|
|
1326
1490
|
}
|
|
1327
1491
|
function extractKeysFromCallExpression(node, keys) {
|
|
1328
1492
|
if (!isI18nCallExpression(node))
|
|
@@ -1333,17 +1497,9 @@ function extractKeysFromCallExpression(node, keys) {
|
|
|
1333
1497
|
const arg = args[0];
|
|
1334
1498
|
if (!isAstNode(arg))
|
|
1335
1499
|
return;
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
const text = getTemplateLiteralText(arg);
|
|
1340
|
-
if (text === void 0)
|
|
1341
|
-
return;
|
|
1342
|
-
if (arg.expressions && Array.isArray(arg.expressions) && arg.expressions.length === 0 && Array.isArray(arg.quasis) && arg.quasis.length === 1)
|
|
1343
|
-
keys.add(text);
|
|
1344
|
-
else if (text)
|
|
1345
|
-
keys.add(`${text}*`);
|
|
1346
|
-
}
|
|
1500
|
+
const key = extractKeyFromArg(arg);
|
|
1501
|
+
if (key)
|
|
1502
|
+
keys.add(key);
|
|
1347
1503
|
}
|
|
1348
1504
|
const TS_AST_CHILD_KEYS = /* @__PURE__ */ new Set([
|
|
1349
1505
|
"alternate",
|
|
@@ -1420,34 +1576,44 @@ function getDirectiveExpression(attr) {
|
|
|
1420
1576
|
function extractKeysFromVueTemplate(templateBody, keys) {
|
|
1421
1577
|
walkVueTemplateNode(templateBody, keys);
|
|
1422
1578
|
}
|
|
1579
|
+
function collectI18nTKeys(element, keys) {
|
|
1580
|
+
if (element.rawName !== "i18n-t" && element.name !== "i18n-t")
|
|
1581
|
+
return;
|
|
1582
|
+
for (const attr of element.startTag.attributes) {
|
|
1583
|
+
if (isKeypathAttribute(attr))
|
|
1584
|
+
keys.add(attr.value.value);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
function collectAttributeKeys(element, keys) {
|
|
1588
|
+
for (const attr of element.startTag.attributes) {
|
|
1589
|
+
const expr = getDirectiveExpression(attr);
|
|
1590
|
+
if (!expr)
|
|
1591
|
+
continue;
|
|
1592
|
+
if (isVTDirective(attr) && expr.type === "Literal" && typeof expr.value === "string")
|
|
1593
|
+
keys.add(expr.value);
|
|
1594
|
+
walkTsAst(expr, keys);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
function walkChildren(node, keys) {
|
|
1598
|
+
if (!("children" in node) || !Array.isArray(node.children))
|
|
1599
|
+
return;
|
|
1600
|
+
for (const child of node.children) {
|
|
1601
|
+
if (child && typeof child === "object")
|
|
1602
|
+
walkVueTemplateNode(child, keys);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1423
1605
|
function walkVueTemplateNode(node, keys) {
|
|
1424
1606
|
if (!node || typeof node !== "object")
|
|
1425
1607
|
return;
|
|
1426
1608
|
if (isVElement(node)) {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
keys.add(attr.value.value);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
for (const attr of node.startTag.attributes) {
|
|
1434
|
-
const expr = getDirectiveExpression(attr);
|
|
1435
|
-
if (!expr)
|
|
1436
|
-
continue;
|
|
1437
|
-
if (isVTDirective(attr) && expr.type === "Literal" && typeof expr.value === "string")
|
|
1438
|
-
keys.add(expr.value);
|
|
1439
|
-
walkTsAst(expr, keys);
|
|
1440
|
-
}
|
|
1441
|
-
for (const child of node.children)
|
|
1442
|
-
walkVueTemplateNode(child, keys);
|
|
1609
|
+
collectI18nTKeys(node, keys);
|
|
1610
|
+
collectAttributeKeys(node, keys);
|
|
1611
|
+
walkChildren(node, keys);
|
|
1443
1612
|
} else if (isVExpressionContainer(node)) {
|
|
1444
1613
|
if (node.expression)
|
|
1445
1614
|
walkTsAst(node.expression, keys);
|
|
1446
|
-
} else
|
|
1447
|
-
|
|
1448
|
-
if (child && typeof child === "object")
|
|
1449
|
-
walkVueTemplateNode(child, keys);
|
|
1450
|
-
}
|
|
1615
|
+
} else {
|
|
1616
|
+
walkChildren(node, keys);
|
|
1451
1617
|
}
|
|
1452
1618
|
}
|
|
1453
1619
|
function extractKeysFromSfcI18nBlock(content, keys) {
|
|
@@ -1501,45 +1667,42 @@ ${content}
|
|
|
1501
1667
|
return void 0;
|
|
1502
1668
|
}
|
|
1503
1669
|
}
|
|
1504
|
-
function
|
|
1505
|
-
const keys = /* @__PURE__ */ new Set();
|
|
1506
|
-
let mtimeMs;
|
|
1507
|
-
try {
|
|
1508
|
-
mtimeMs = statSync(filePath).mtimeMs;
|
|
1509
|
-
} catch {
|
|
1510
|
-
return keys;
|
|
1511
|
-
}
|
|
1512
|
-
const cached = fileCache.get(filePath);
|
|
1513
|
-
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1514
|
-
return cached.keys;
|
|
1515
|
-
}
|
|
1516
|
-
let content;
|
|
1670
|
+
function readFileWithMtime(filePath) {
|
|
1517
1671
|
try {
|
|
1518
|
-
|
|
1672
|
+
const mtimeMs = statSync(filePath).mtimeMs;
|
|
1673
|
+
const content = readFileSync(filePath, "utf-8");
|
|
1674
|
+
return { content, mtimeMs };
|
|
1519
1675
|
} catch {
|
|
1520
|
-
return
|
|
1521
|
-
}
|
|
1522
|
-
const isVue = filePath.endsWith(".vue");
|
|
1523
|
-
const pattern = isVue ? VUE_I18N_PATTERN : I18N_CALL_PATTERN;
|
|
1524
|
-
if (!pattern.test(content)) {
|
|
1525
|
-
fileCache.set(filePath, { keys, mtimeMs });
|
|
1526
|
-
return keys;
|
|
1676
|
+
return void 0;
|
|
1527
1677
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
return keys;
|
|
1678
|
+
}
|
|
1679
|
+
function extractKeysFromAst(ast, content, isVue, keys) {
|
|
1531
1680
|
if (isVue) {
|
|
1532
|
-
if (ast.templateBody)
|
|
1681
|
+
if (ast.templateBody)
|
|
1533
1682
|
extractKeysFromVueTemplate(ast.templateBody, keys);
|
|
1534
|
-
}
|
|
1535
1683
|
extractKeysFromSfcI18nBlock(content, keys);
|
|
1536
1684
|
}
|
|
1537
1685
|
if (ast.body) {
|
|
1538
|
-
for (const node of ast.body)
|
|
1686
|
+
for (const node of ast.body)
|
|
1539
1687
|
walkTsAst(node, keys);
|
|
1540
|
-
}
|
|
1541
1688
|
}
|
|
1542
|
-
|
|
1689
|
+
}
|
|
1690
|
+
function collectKeysFromFile(filePath) {
|
|
1691
|
+
const file = readFileWithMtime(filePath);
|
|
1692
|
+
if (!file)
|
|
1693
|
+
return /* @__PURE__ */ new Set();
|
|
1694
|
+
const cached = fileCache.get(filePath);
|
|
1695
|
+
if (cached && cached.mtimeMs === file.mtimeMs)
|
|
1696
|
+
return cached.keys;
|
|
1697
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1698
|
+
const isVue = filePath.endsWith(".vue");
|
|
1699
|
+
const pattern = isVue ? VUE_I18N_PATTERN : I18N_CALL_PATTERN;
|
|
1700
|
+
if (pattern.test(file.content)) {
|
|
1701
|
+
const ast = parseSourceFile(file.content, filePath);
|
|
1702
|
+
if (ast)
|
|
1703
|
+
extractKeysFromAst(ast, file.content, isVue, keys);
|
|
1704
|
+
}
|
|
1705
|
+
fileCache.set(filePath, { keys, mtimeMs: file.mtimeMs });
|
|
1543
1706
|
return keys;
|
|
1544
1707
|
}
|
|
1545
1708
|
function collectAllUsedKeys(srcDir, extensions) {
|
|
@@ -1613,21 +1776,22 @@ const debug = debugFactory("@rotki/eslint-plugin:no-unused-i18n-keys");
|
|
|
1613
1776
|
function isLocaleFile(filename) {
|
|
1614
1777
|
return /(?:locales?|i18n|translations?|messages?|lang)\b/i.test(filename);
|
|
1615
1778
|
}
|
|
1616
|
-
function
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1779
|
+
function isProgramWithBody(ast) {
|
|
1780
|
+
return !!ast && typeof ast === "object" && "type" in ast && ast.type === "Program" && "body" in ast && Array.isArray(ast.body) && ast.body.length > 0;
|
|
1781
|
+
}
|
|
1782
|
+
function getProgramFirstBodyType(ast) {
|
|
1783
|
+
if (!isProgramWithBody(ast))
|
|
1784
|
+
return void 0;
|
|
1621
1785
|
const first = ast.body[0];
|
|
1622
|
-
|
|
1786
|
+
if (!first || typeof first !== "object" || !("type" in first) || typeof first.type !== "string")
|
|
1787
|
+
return void 0;
|
|
1788
|
+
return first.type;
|
|
1789
|
+
}
|
|
1790
|
+
function isJsonProgram(ast) {
|
|
1791
|
+
return getProgramFirstBodyType(ast) === "JSONExpressionStatement";
|
|
1623
1792
|
}
|
|
1624
1793
|
function isYamlProgram(ast) {
|
|
1625
|
-
|
|
1626
|
-
return false;
|
|
1627
|
-
if (!("body" in ast) || !Array.isArray(ast.body) || ast.body.length === 0)
|
|
1628
|
-
return false;
|
|
1629
|
-
const first = ast.body[0];
|
|
1630
|
-
return first !== null && typeof first === "object" && "type" in first && first.type === "YAMLDocument";
|
|
1794
|
+
return getProgramFirstBodyType(ast) === "YAMLDocument";
|
|
1631
1795
|
}
|
|
1632
1796
|
function buildJsonKeyPaths(node, prefix, paths) {
|
|
1633
1797
|
for (const prop of node.properties) {
|
|
@@ -1928,6 +2092,7 @@ const plugin = {
|
|
|
1928
2092
|
"no-deprecated-props": noDeprecatedProps,
|
|
1929
2093
|
"no-dot-ts-imports": noDotTsImport,
|
|
1930
2094
|
"no-legacy-library-import": noLegacyLibraryImport,
|
|
2095
|
+
"no-redundant-flex-row": noRedundantFlexRow,
|
|
1931
2096
|
"no-unused-i18n-keys": noUnusedI18nKeys,
|
|
1932
2097
|
"require-jsdoc-on-composable-options": requireJsdocOnComposableOptions
|
|
1933
2098
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rotki/eslint-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"bugs": {
|
|
@@ -25,43 +25,44 @@
|
|
|
25
25
|
},
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"eslint": "^9.20.0"
|
|
28
|
+
"eslint": "^9.20.0 || ^10.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@typescript-eslint/utils": "8.
|
|
31
|
+
"@typescript-eslint/utils": "8.60.1",
|
|
32
32
|
"debug": "4.4.3",
|
|
33
|
-
"eslint-
|
|
34
|
-
"jsonc-eslint-parser": "2.4.2",
|
|
33
|
+
"jsonc-eslint-parser": "3.1.0",
|
|
35
34
|
"scule": "1.3.0",
|
|
36
|
-
"tinyglobby": "0.2.
|
|
37
|
-
"vue-eslint-parser": "10.4.
|
|
35
|
+
"tinyglobby": "0.2.17",
|
|
36
|
+
"vue-eslint-parser": "10.4.1",
|
|
38
37
|
"yaml-eslint-parser": "2.0.0"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
|
-
"@commitlint/cli": "
|
|
42
|
-
"@commitlint/config-conventional": "
|
|
43
|
-
"@rotki/eslint-config": "
|
|
44
|
-
"@rotki/eslint-plugin": "1.2
|
|
45
|
-
"@types/debug": "4.1.
|
|
46
|
-
"@types/node": "24.
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
48
|
-
"@typescript-eslint/parser": "8.
|
|
49
|
-
"@typescript-eslint/rule-tester": "8.
|
|
50
|
-
"@vitest/coverage-v8": "4.
|
|
51
|
-
"bumpp": "
|
|
52
|
-
"eslint": "
|
|
40
|
+
"@commitlint/cli": "21.0.2",
|
|
41
|
+
"@commitlint/config-conventional": "21.0.2",
|
|
42
|
+
"@rotki/eslint-config": "6.1.0",
|
|
43
|
+
"@rotki/eslint-plugin": "1.3.2",
|
|
44
|
+
"@types/debug": "4.1.13",
|
|
45
|
+
"@types/node": "24.13.1",
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "8.60.1",
|
|
47
|
+
"@typescript-eslint/parser": "8.60.1",
|
|
48
|
+
"@typescript-eslint/rule-tester": "8.60.1",
|
|
49
|
+
"@vitest/coverage-v8": "4.1.8",
|
|
50
|
+
"bumpp": "11.1.0",
|
|
51
|
+
"eslint": "10.4.1",
|
|
53
52
|
"husky": "9.1.7",
|
|
54
|
-
"lint-staged": "
|
|
53
|
+
"lint-staged": "17.0.7",
|
|
54
|
+
"oxc-minify": "0.135.0",
|
|
55
|
+
"prettier": "3.8.1",
|
|
55
56
|
"rimraf": "6.1.3",
|
|
56
|
-
"tsx": "4.
|
|
57
|
-
"typescript": "
|
|
57
|
+
"tsx": "4.22.4",
|
|
58
|
+
"typescript": "6.0.3",
|
|
58
59
|
"unbuild": "3.6.1",
|
|
59
|
-
"vitepress": "
|
|
60
|
-
"vitest": "4.
|
|
60
|
+
"vitepress": "2.0.0-alpha.17",
|
|
61
|
+
"vitest": "4.1.8"
|
|
61
62
|
},
|
|
62
63
|
"engines": {
|
|
63
64
|
"node": ">=24 <25",
|
|
64
|
-
"pnpm": ">=10 <
|
|
65
|
+
"pnpm": ">=10 <12"
|
|
65
66
|
},
|
|
66
67
|
"lint-staged": {
|
|
67
68
|
"*.{js,cjs,ts,vue,yml,json,md}": "eslint"
|