@taiga-ui/eslint-plugin-experience-next 0.475.0 → 0.477.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 +63 -0
- package/index.d.ts +10 -1
- package/index.esm.js +242 -60
- package/package.json +1 -1
- package/rules/no-commonjs-import-patterns.d.ts +6 -0
- package/rules/no-import-assertions.d.ts +5 -0
- package/rules/no-infinite-loop.d.ts +1 -1
- package/rules/prefer-namespace-keyword.d.ts +5 -0
package/README.md
CHANGED
|
@@ -45,10 +45,12 @@ export default [
|
|
|
45
45
|
| flat-exports | Spread nested arrays when exporting Angular entity collections | | 🔧 | |
|
|
46
46
|
| host-attributes-sort | Sort Angular host metadata attributes using configurable attribute groups | ✅ | 🔧 | |
|
|
47
47
|
| injection-token-description | Require `InjectionToken` descriptions to include the token name | ✅ | 🔧 | |
|
|
48
|
+
| no-commonjs-import-patterns | Disallow legacy CommonJS interop import patterns | ✅ | | |
|
|
48
49
|
| no-deep-imports | Disables deep imports of Taiga UI packages | ✅ | 🔧 | |
|
|
49
50
|
| no-deep-imports-to-indexed-packages | Disallow deep imports from packages that expose an index.ts next to ng-package.json or package.json | ✅ | 🔧 | |
|
|
50
51
|
| no-fully-untracked-effect | Disallow reactive callbacks where all signal reads are hidden inside `untracked()` | ✅ | | |
|
|
51
52
|
| no-href-with-router-link | Do not use href and routerLink attributes together on the same element | ✅ | 🔧 | |
|
|
53
|
+
| no-import-assertions | Replace legacy `assert { ... }` import assertions with `with { ... }` | ✅ | 🔧 | |
|
|
52
54
|
| no-implicit-public | Require explicit `public` modifier for class members and parameter properties | ✅ | 🔧 | |
|
|
53
55
|
| no-infinite-loop | Disallow `while (true)` and `for` loops without an explicit condition | ✅ | | |
|
|
54
56
|
| no-legacy-peer-deps | Disallow `legacy-peer-deps=true` in `.npmrc` | ✅ | | |
|
|
@@ -64,6 +66,7 @@ export default [
|
|
|
64
66
|
| prefer-combined-if-control-flow | Combine consecutive `if` statements that use the same `return`, `break`, `continue`, or `throw` | ✅ | 🔧 | |
|
|
65
67
|
| prefer-deep-imports | Allow deep imports of Taiga UI packages | | 🔧 | |
|
|
66
68
|
| prefer-multi-arg-push | Combine consecutive `.push()` calls on the same array into a single multi-argument call | ✅ | 🔧 | |
|
|
69
|
+
| prefer-namespace-keyword | Replace `module Foo {}` with `namespace Foo {}` for TypeScript namespace declarations | ✅ | 🔧 | |
|
|
67
70
|
| prefer-untracked-incidental-signal-reads | Wrap likely-incidental signal reads with `untracked()` in reactive callbacks | ✅ | 🔧 | |
|
|
68
71
|
| prefer-untracked-signal-getter | Prefer `untracked(signalGetter)` over `untracked(() => signalGetter())` for a single signal getter | ✅ | 🔧 | |
|
|
69
72
|
| short-tui-imports | Shorten TuiXxxComponent / TuiYyyDirective in Angular metadata | ✅ | 🔧 | |
|
|
@@ -307,6 +310,29 @@ export const TUI_MY_TOKEN = new InjectionToken<string>(ngDevMode ? '[TUI_MY_TOKE
|
|
|
307
310
|
|
|
308
311
|
---
|
|
309
312
|
|
|
313
|
+
## no-commonjs-import-patterns
|
|
314
|
+
|
|
315
|
+
<sup>`✅ Recommended`</sup>
|
|
316
|
+
|
|
317
|
+
Disallows legacy CommonJS interop import patterns that are brittle under modern ESM-oriented toolchains. It reports
|
|
318
|
+
`import foo = require('foo')` and namespace imports that are used as callable values, constructors, or tag functions.
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
// ❌ error
|
|
322
|
+
import toolkit = require('@taiga-ui/cdk');
|
|
323
|
+
|
|
324
|
+
import * as createClient from 'legacy-client';
|
|
325
|
+
createClient();
|
|
326
|
+
|
|
327
|
+
// ✅ ok
|
|
328
|
+
import toolkit from '@taiga-ui/cdk';
|
|
329
|
+
|
|
330
|
+
import createClient from 'legacy-client';
|
|
331
|
+
createClient();
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
310
336
|
## no-deep-imports
|
|
311
337
|
|
|
312
338
|
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
@@ -419,6 +445,22 @@ attribute.
|
|
|
419
445
|
|
|
420
446
|
---
|
|
421
447
|
|
|
448
|
+
## no-import-assertions
|
|
449
|
+
|
|
450
|
+
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
451
|
+
|
|
452
|
+
Disallows legacy `assert { ... }` import assertions and rewrites them to `with { ... }` import attributes.
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
// ❌ error
|
|
456
|
+
import data from './file.json' assert {type: 'json'};
|
|
457
|
+
|
|
458
|
+
// ✅ after autofix
|
|
459
|
+
import data from './file.json' with {type: 'json'};
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
422
464
|
## no-implicit-public
|
|
423
465
|
|
|
424
466
|
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
@@ -1043,6 +1085,27 @@ output.push('# Getting Started', '');
|
|
|
1043
1085
|
|
|
1044
1086
|
---
|
|
1045
1087
|
|
|
1088
|
+
## prefer-namespace-keyword
|
|
1089
|
+
|
|
1090
|
+
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
|
1091
|
+
|
|
1092
|
+
Prefers `namespace Foo {}` over the older `module Foo {}` syntax for TypeScript namespace declarations. External module
|
|
1093
|
+
augmentations such as `declare module 'pkg' {}` are ignored.
|
|
1094
|
+
|
|
1095
|
+
```ts
|
|
1096
|
+
// ❌ error
|
|
1097
|
+
module Foo.Bar {
|
|
1098
|
+
export type Value = string;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// ✅ after autofix
|
|
1102
|
+
namespace Foo.Bar {
|
|
1103
|
+
export type Value = string;
|
|
1104
|
+
}
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
---
|
|
1108
|
+
|
|
1046
1109
|
## prefer-untracked-incidental-signal-reads
|
|
1047
1110
|
|
|
1048
1111
|
<sup>`✅ Recommended`</sup> <sup>`Fixable`</sup>
|
package/index.d.ts
CHANGED
|
@@ -30,6 +30,9 @@ declare const plugin: {
|
|
|
30
30
|
'injection-token-description': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalid-injection-token-description", readonly unknown[], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
31
31
|
name: string;
|
|
32
32
|
};
|
|
33
|
+
'no-commonjs-import-patterns': import("@typescript-eslint/utils/ts-eslint").RuleModule<"avoidCallableNamespaceImport" | "avoidImportEquals", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
33
36
|
'no-deep-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"no-deep-imports", {
|
|
34
37
|
currentProject: string;
|
|
35
38
|
deepImport: string;
|
|
@@ -49,7 +52,10 @@ declare const plugin: {
|
|
|
49
52
|
'no-implicit-public': import("@typescript-eslint/utils/ts-eslint").RuleModule<"implicitPublic", readonly unknown[], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
50
53
|
name: string;
|
|
51
54
|
};
|
|
52
|
-
'no-
|
|
55
|
+
'no-import-assertions': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useWithImportAttributes", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
56
|
+
name: string;
|
|
57
|
+
};
|
|
58
|
+
'no-infinite-loop': import("@typescript-eslint/utils/ts-eslint").RuleModule<"doWhileLoop" | "forLoop" | "whileLoop", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
53
59
|
name: string;
|
|
54
60
|
};
|
|
55
61
|
'no-legacy-peer-deps': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noLegacyPeerDeps", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
@@ -96,6 +102,9 @@ declare const plugin: {
|
|
|
96
102
|
'prefer-multi-arg-push': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferMultiArgPush", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
97
103
|
name: string;
|
|
98
104
|
};
|
|
105
|
+
'prefer-namespace-keyword': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useNamespaceKeyword", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
106
|
+
name: string;
|
|
107
|
+
};
|
|
99
108
|
'prefer-untracked-incidental-signal-reads': import("@typescript-eslint/utils/ts-eslint").RuleModule<"incidentalRead", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
100
109
|
name: string;
|
|
101
110
|
};
|
package/index.esm.js
CHANGED
|
@@ -898,6 +898,7 @@ var recommended = defineConfig([
|
|
|
898
898
|
],
|
|
899
899
|
'@taiga-ui/experience-next/host-attributes-sort': 'error',
|
|
900
900
|
'@taiga-ui/experience-next/injection-token-description': 'error',
|
|
901
|
+
'@taiga-ui/experience-next/no-commonjs-import-patterns': 'error',
|
|
901
902
|
'@taiga-ui/experience-next/no-deep-imports': [
|
|
902
903
|
'error',
|
|
903
904
|
{
|
|
@@ -908,6 +909,7 @@ var recommended = defineConfig([
|
|
|
908
909
|
'@taiga-ui/experience-next/no-deep-imports-to-indexed-packages': 'error',
|
|
909
910
|
'@taiga-ui/experience-next/no-fully-untracked-effect': 'error',
|
|
910
911
|
'@taiga-ui/experience-next/no-implicit-public': 'error',
|
|
912
|
+
'@taiga-ui/experience-next/no-import-assertions': 'error',
|
|
911
913
|
'@taiga-ui/experience-next/no-infinite-loop': 'error',
|
|
912
914
|
'@taiga-ui/experience-next/no-redundant-type-annotation': 'error',
|
|
913
915
|
'@taiga-ui/experience-next/no-side-effects-in-computed': 'error',
|
|
@@ -917,6 +919,7 @@ var recommended = defineConfig([
|
|
|
917
919
|
'@taiga-ui/experience-next/object-single-line': ['error', { printWidth: 90 }],
|
|
918
920
|
'@taiga-ui/experience-next/prefer-combined-if-control-flow': 'error',
|
|
919
921
|
'@taiga-ui/experience-next/prefer-multi-arg-push': 'error',
|
|
922
|
+
'@taiga-ui/experience-next/prefer-namespace-keyword': 'error',
|
|
920
923
|
'@taiga-ui/experience-next/prefer-untracked-incidental-signal-reads': 'error',
|
|
921
924
|
'@taiga-ui/experience-next/prefer-untracked-signal-getter': 'error',
|
|
922
925
|
'@taiga-ui/experience-next/short-tui-imports': 'error',
|
|
@@ -1351,8 +1354,8 @@ function getTypeAwareRuleContext(context) {
|
|
|
1351
1354
|
};
|
|
1352
1355
|
}
|
|
1353
1356
|
|
|
1354
|
-
const createRule$
|
|
1355
|
-
var classPropertyNaming = createRule$
|
|
1357
|
+
const createRule$m = ESLintUtils.RuleCreator((name) => name);
|
|
1358
|
+
var classPropertyNaming = createRule$m({
|
|
1356
1359
|
create(context, [configs]) {
|
|
1357
1360
|
const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
|
|
1358
1361
|
const flatConfig = configs.flat();
|
|
@@ -1520,9 +1523,9 @@ function isExternalPureTuple(typeChecker, type) {
|
|
|
1520
1523
|
return typeArgs.every((item) => isClassType(item));
|
|
1521
1524
|
}
|
|
1522
1525
|
|
|
1523
|
-
const createRule$
|
|
1526
|
+
const createRule$l = ESLintUtils.RuleCreator((name) => name);
|
|
1524
1527
|
const MESSAGE_ID$7 = 'spreadArrays';
|
|
1525
|
-
var flatExports = createRule$
|
|
1528
|
+
var flatExports = createRule$l({
|
|
1526
1529
|
create(context) {
|
|
1527
1530
|
const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
|
|
1528
1531
|
const arrays = new Map();
|
|
@@ -1802,8 +1805,8 @@ const PRESETS = {
|
|
|
1802
1805
|
$VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
|
|
1803
1806
|
$VUE_ATTRIBUTE: /^v-/,
|
|
1804
1807
|
};
|
|
1805
|
-
const createRule$
|
|
1806
|
-
const rule$
|
|
1808
|
+
const createRule$k = ESLintUtils.RuleCreator((name) => name);
|
|
1809
|
+
const rule$n = createRule$k({
|
|
1807
1810
|
create(context, [options]) {
|
|
1808
1811
|
const sourceCode = context.sourceCode;
|
|
1809
1812
|
const settings = {
|
|
@@ -2064,7 +2067,7 @@ const config$2 = {
|
|
|
2064
2067
|
const MESSAGE_ID$5 = 'invalid-injection-token-description';
|
|
2065
2068
|
const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
|
|
2066
2069
|
const NG_DEV_MODE = 'ngDevMode';
|
|
2067
|
-
const createRule$
|
|
2070
|
+
const createRule$j = ESLintUtils.RuleCreator((name) => name);
|
|
2068
2071
|
function getVariableName(node) {
|
|
2069
2072
|
if (node.parent.type !== AST_NODE_TYPES$1.VariableDeclarator) {
|
|
2070
2073
|
return undefined;
|
|
@@ -2132,7 +2135,7 @@ function getNgDevModeDeclarationFix(program, fixer) {
|
|
|
2132
2135
|
}
|
|
2133
2136
|
return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
|
|
2134
2137
|
}
|
|
2135
|
-
const rule$
|
|
2138
|
+
const rule$m = createRule$j({
|
|
2136
2139
|
create(context) {
|
|
2137
2140
|
const { sourceCode } = context;
|
|
2138
2141
|
const program = sourceCode.ast;
|
|
@@ -2181,6 +2184,88 @@ const rule$j = createRule$g({
|
|
|
2181
2184
|
name: 'injection-token-description',
|
|
2182
2185
|
});
|
|
2183
2186
|
|
|
2187
|
+
const createRule$i = ESLintUtils.RuleCreator((name) => name);
|
|
2188
|
+
function getResolvedVariable(sourceCode, node) {
|
|
2189
|
+
const scope = sourceCode.getScope(node);
|
|
2190
|
+
const reference = scope.references.find((item) => item.identifier === node);
|
|
2191
|
+
return reference?.resolved ?? null;
|
|
2192
|
+
}
|
|
2193
|
+
const rule$l = createRule$i({
|
|
2194
|
+
create(context) {
|
|
2195
|
+
const { sourceCode } = context;
|
|
2196
|
+
const namespaceImports = new Map();
|
|
2197
|
+
const markNamespaceImportAsUsedLikeValue = (identifier) => {
|
|
2198
|
+
const usage = namespaceImports.get(identifier.name);
|
|
2199
|
+
if (!usage ||
|
|
2200
|
+
usage.usedLikeValue ||
|
|
2201
|
+
getResolvedVariable(sourceCode, identifier) !== usage.variable) {
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
usage.usedLikeValue = true;
|
|
2205
|
+
};
|
|
2206
|
+
return {
|
|
2207
|
+
'CallExpression > Identifier.callee'(node) {
|
|
2208
|
+
markNamespaceImportAsUsedLikeValue(node);
|
|
2209
|
+
},
|
|
2210
|
+
ImportDeclaration(node) {
|
|
2211
|
+
const namespaceImport = node.specifiers.find((specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier);
|
|
2212
|
+
if (!namespaceImport) {
|
|
2213
|
+
return;
|
|
2214
|
+
}
|
|
2215
|
+
const [variable] = sourceCode.getDeclaredVariables(namespaceImport);
|
|
2216
|
+
if (!variable) {
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
namespaceImports.set(namespaceImport.local.name, {
|
|
2220
|
+
node: namespaceImport,
|
|
2221
|
+
usedLikeValue: false,
|
|
2222
|
+
variable,
|
|
2223
|
+
});
|
|
2224
|
+
},
|
|
2225
|
+
'NewExpression > Identifier.callee'(node) {
|
|
2226
|
+
markNamespaceImportAsUsedLikeValue(node);
|
|
2227
|
+
},
|
|
2228
|
+
'Program:exit'() {
|
|
2229
|
+
for (const usage of namespaceImports.values()) {
|
|
2230
|
+
if (!usage.usedLikeValue) {
|
|
2231
|
+
continue;
|
|
2232
|
+
}
|
|
2233
|
+
context.report({
|
|
2234
|
+
data: { name: usage.node.local.name },
|
|
2235
|
+
messageId: 'avoidCallableNamespaceImport',
|
|
2236
|
+
node: usage.node,
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
},
|
|
2240
|
+
'TaggedTemplateExpression > Identifier.tag'(node) {
|
|
2241
|
+
markNamespaceImportAsUsedLikeValue(node);
|
|
2242
|
+
},
|
|
2243
|
+
TSImportEqualsDeclaration(node) {
|
|
2244
|
+
if (node.moduleReference.type !== AST_NODE_TYPES.TSExternalModuleReference) {
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
context.report({
|
|
2248
|
+
data: { name: node.id.name },
|
|
2249
|
+
messageId: 'avoidImportEquals',
|
|
2250
|
+
node,
|
|
2251
|
+
});
|
|
2252
|
+
},
|
|
2253
|
+
};
|
|
2254
|
+
},
|
|
2255
|
+
meta: {
|
|
2256
|
+
docs: {
|
|
2257
|
+
description: 'Disallow legacy CommonJS interop import patterns such as `import = require(...)` and namespace imports used like callable values.',
|
|
2258
|
+
},
|
|
2259
|
+
messages: {
|
|
2260
|
+
avoidCallableNamespaceImport: 'Namespace import "{{name}}" is used like a value instead of a namespace. This is a brittle interop pattern and often should become a default import.',
|
|
2261
|
+
avoidImportEquals: '`import {{name}} = require(...)` is a legacy CommonJS import pattern.',
|
|
2262
|
+
},
|
|
2263
|
+
schema: [],
|
|
2264
|
+
type: 'problem',
|
|
2265
|
+
},
|
|
2266
|
+
name: 'no-commonjs-import-patterns',
|
|
2267
|
+
});
|
|
2268
|
+
|
|
2184
2269
|
const MESSAGE_ID$4 = 'no-deep-imports';
|
|
2185
2270
|
const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
|
|
2186
2271
|
const CODE_EXTENSIONS = new Set([
|
|
@@ -2200,8 +2285,8 @@ const DEFAULT_OPTIONS = {
|
|
|
2200
2285
|
importDeclaration: '^@taiga-ui*',
|
|
2201
2286
|
projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
|
|
2202
2287
|
};
|
|
2203
|
-
const createRule$
|
|
2204
|
-
const rule$
|
|
2288
|
+
const createRule$h = ESLintUtils.RuleCreator((name) => name);
|
|
2289
|
+
const rule$k = createRule$h({
|
|
2205
2290
|
create(context) {
|
|
2206
2291
|
const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
|
|
2207
2292
|
const hasNonCodeExtension = (source) => {
|
|
@@ -2288,13 +2373,13 @@ const rule$i = createRule$f({
|
|
|
2288
2373
|
name: 'no-deep-imports',
|
|
2289
2374
|
});
|
|
2290
2375
|
|
|
2291
|
-
const createRule$
|
|
2376
|
+
const createRule$g = ESLintUtils.RuleCreator((name) => name);
|
|
2292
2377
|
const resolveCacheByOptions = new WeakMap();
|
|
2293
2378
|
const nearestFileUpCache = new Map();
|
|
2294
2379
|
const markerCache = new Map();
|
|
2295
2380
|
const indexFileCache = new Map();
|
|
2296
2381
|
const indexExportsCache = new Map();
|
|
2297
|
-
var noDeepImportsToIndexedPackages = createRule$
|
|
2382
|
+
var noDeepImportsToIndexedPackages = createRule$g({
|
|
2298
2383
|
create(context) {
|
|
2299
2384
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
2300
2385
|
const program = parserServices.program;
|
|
@@ -3014,7 +3099,7 @@ const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#react
|
|
|
3014
3099
|
const UNTRACKED_RULES_README_URL = 'https://github.com/taiga-family/taiga-ui/blob/main/projects/eslint-plugin-experience-next/README.md';
|
|
3015
3100
|
const createUntrackedRule = ESLintUtils.RuleCreator((name) => `${UNTRACKED_RULES_README_URL}#${name}`);
|
|
3016
3101
|
|
|
3017
|
-
const rule$
|
|
3102
|
+
const rule$j = createUntrackedRule({
|
|
3018
3103
|
create(context) {
|
|
3019
3104
|
const { checker, esTreeNodeToTSNodeMap, program } = getTypeAwareRuleContext(context);
|
|
3020
3105
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -3153,8 +3238,8 @@ function getScopeRoot(node) {
|
|
|
3153
3238
|
return (findAncestor(node, (ancestor) => ancestor.type === AST_NODE_TYPES.Program || isFunctionLike(ancestor)) ?? node);
|
|
3154
3239
|
}
|
|
3155
3240
|
|
|
3156
|
-
const createRule$
|
|
3157
|
-
const rule$
|
|
3241
|
+
const createRule$f = ESLintUtils.RuleCreator((name) => name);
|
|
3242
|
+
const rule$i = createRule$f({
|
|
3158
3243
|
create(context) {
|
|
3159
3244
|
const checkImplicitPublic = (node) => {
|
|
3160
3245
|
const classRef = getEnclosingClass(node);
|
|
@@ -3216,6 +3301,38 @@ const rule$g = createRule$d({
|
|
|
3216
3301
|
name: 'explicit-public-member',
|
|
3217
3302
|
});
|
|
3218
3303
|
|
|
3304
|
+
const createRule$e = ESLintUtils.RuleCreator((name) => name);
|
|
3305
|
+
const rule$h = createRule$e({
|
|
3306
|
+
create(context) {
|
|
3307
|
+
const { sourceCode } = context;
|
|
3308
|
+
return {
|
|
3309
|
+
ImportDeclaration(node) {
|
|
3310
|
+
const importAttributesToken = sourceCode.getTokenAfter(node.source);
|
|
3311
|
+
if (importAttributesToken?.value !== 'assert') {
|
|
3312
|
+
return;
|
|
3313
|
+
}
|
|
3314
|
+
context.report({
|
|
3315
|
+
fix: (fixer) => fixer.replaceText(importAttributesToken, 'with'),
|
|
3316
|
+
messageId: 'useWithImportAttributes',
|
|
3317
|
+
node: importAttributesToken,
|
|
3318
|
+
});
|
|
3319
|
+
},
|
|
3320
|
+
};
|
|
3321
|
+
},
|
|
3322
|
+
meta: {
|
|
3323
|
+
docs: {
|
|
3324
|
+
description: 'Disallow legacy `assert { ... }` import assertions. Use `with { ... }` import attributes instead.',
|
|
3325
|
+
},
|
|
3326
|
+
fixable: 'code',
|
|
3327
|
+
messages: {
|
|
3328
|
+
useWithImportAttributes: 'Use `with { ... }` import attributes instead of `assert { ... }`.',
|
|
3329
|
+
},
|
|
3330
|
+
schema: [],
|
|
3331
|
+
type: 'problem',
|
|
3332
|
+
},
|
|
3333
|
+
name: 'no-import-assertions',
|
|
3334
|
+
});
|
|
3335
|
+
|
|
3219
3336
|
function getParenthesizedInner(node) {
|
|
3220
3337
|
const maybeNode = node;
|
|
3221
3338
|
if (maybeNode.type === 'ParenthesizedExpression') {
|
|
@@ -3233,16 +3350,30 @@ function unwrapParenthesized(node) {
|
|
|
3233
3350
|
return current;
|
|
3234
3351
|
}
|
|
3235
3352
|
|
|
3236
|
-
const createRule$
|
|
3237
|
-
function
|
|
3353
|
+
const createRule$d = ESLintUtils.RuleCreator((name) => name);
|
|
3354
|
+
function isInfiniteLoopLiteral(node) {
|
|
3238
3355
|
const unwrapped = unwrapParenthesized(node);
|
|
3239
|
-
|
|
3356
|
+
if (unwrapped.type !== AST_NODE_TYPES.Literal) {
|
|
3357
|
+
return false;
|
|
3358
|
+
}
|
|
3359
|
+
return unwrapped.value === true || unwrapped.value === 1;
|
|
3240
3360
|
}
|
|
3241
|
-
|
|
3361
|
+
function isInfiniteLoopTest(test) {
|
|
3362
|
+
return test === null || isInfiniteLoopLiteral(test);
|
|
3363
|
+
}
|
|
3364
|
+
const rule$g = createRule$d({
|
|
3242
3365
|
create(context) {
|
|
3243
3366
|
return {
|
|
3367
|
+
DoWhileStatement(node) {
|
|
3368
|
+
if (isInfiniteLoopTest(node.test)) {
|
|
3369
|
+
context.report({
|
|
3370
|
+
messageId: 'doWhileLoop',
|
|
3371
|
+
node: node.test,
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
},
|
|
3244
3375
|
ForStatement(node) {
|
|
3245
|
-
if (
|
|
3376
|
+
if (isInfiniteLoopTest(node.test)) {
|
|
3246
3377
|
context.report({
|
|
3247
3378
|
messageId: 'forLoop',
|
|
3248
3379
|
node,
|
|
@@ -3250,7 +3381,7 @@ const rule$f = createRule$c({
|
|
|
3250
3381
|
}
|
|
3251
3382
|
},
|
|
3252
3383
|
WhileStatement(node) {
|
|
3253
|
-
if (
|
|
3384
|
+
if (isInfiniteLoopTest(node.test)) {
|
|
3254
3385
|
context.report({
|
|
3255
3386
|
messageId: 'whileLoop',
|
|
3256
3387
|
node: node.test,
|
|
@@ -3261,9 +3392,10 @@ const rule$f = createRule$c({
|
|
|
3261
3392
|
},
|
|
3262
3393
|
meta: {
|
|
3263
3394
|
docs: {
|
|
3264
|
-
description: 'Disallow `
|
|
3395
|
+
description: 'Disallow `for (;;)` / conditionals `for`, `while (true)`, and `do ... while (true)`. Prefer loops with meaningful exit conditions.',
|
|
3265
3396
|
},
|
|
3266
3397
|
messages: {
|
|
3398
|
+
doWhileLoop: 'Use an explicit exit condition instead of `do ... while (true)`.',
|
|
3267
3399
|
forLoop: 'Use an explicit exit condition instead of a `for` loop without a condition.',
|
|
3268
3400
|
whileLoop: 'Use an explicit exit condition instead of `while (true)`.',
|
|
3269
3401
|
},
|
|
@@ -3273,9 +3405,9 @@ const rule$f = createRule$c({
|
|
|
3273
3405
|
name: 'no-infinite-loop',
|
|
3274
3406
|
});
|
|
3275
3407
|
|
|
3276
|
-
const createRule$
|
|
3408
|
+
const createRule$c = ESLintUtils.RuleCreator((name) => name);
|
|
3277
3409
|
const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
|
|
3278
|
-
const rule$
|
|
3410
|
+
const rule$f = createRule$c({
|
|
3279
3411
|
create(context) {
|
|
3280
3412
|
return {
|
|
3281
3413
|
Program(node) {
|
|
@@ -3313,8 +3445,8 @@ const rule$e = createRule$b({
|
|
|
3313
3445
|
name: 'no-legacy-peer-deps',
|
|
3314
3446
|
});
|
|
3315
3447
|
|
|
3316
|
-
const createRule$
|
|
3317
|
-
const rule$
|
|
3448
|
+
const createRule$b = ESLintUtils.RuleCreator((name) => name);
|
|
3449
|
+
const rule$e = createRule$b({
|
|
3318
3450
|
create(context) {
|
|
3319
3451
|
const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
|
|
3320
3452
|
return {
|
|
@@ -3471,7 +3603,7 @@ const config = {
|
|
|
3471
3603
|
},
|
|
3472
3604
|
};
|
|
3473
3605
|
|
|
3474
|
-
const createRule$
|
|
3606
|
+
const createRule$a = ESLintUtils.RuleCreator((name) => name);
|
|
3475
3607
|
function collectArrayExpressions(node) {
|
|
3476
3608
|
const result = [];
|
|
3477
3609
|
if (node.type === AST_NODE_TYPES.ArrayExpression) {
|
|
@@ -3497,7 +3629,7 @@ function collectArrayExpressions(node) {
|
|
|
3497
3629
|
}
|
|
3498
3630
|
return result;
|
|
3499
3631
|
}
|
|
3500
|
-
const rule$
|
|
3632
|
+
const rule$d = createRule$a({
|
|
3501
3633
|
create(context) {
|
|
3502
3634
|
const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
|
|
3503
3635
|
const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
|
|
@@ -3666,7 +3798,7 @@ function getSymbolAtNode(node, checker, esTreeNodeToTSNodeMap) {
|
|
|
3666
3798
|
return checker.getSymbolAtLocation(tsNode) ?? null;
|
|
3667
3799
|
}
|
|
3668
3800
|
|
|
3669
|
-
const createRule$
|
|
3801
|
+
const createRule$9 = ESLintUtils.RuleCreator((name) => name);
|
|
3670
3802
|
function isFunctionLikeScope(node) {
|
|
3671
3803
|
return !!node && isFunctionLike(node);
|
|
3672
3804
|
}
|
|
@@ -3923,7 +4055,7 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
|
|
|
3923
4055
|
return;
|
|
3924
4056
|
});
|
|
3925
4057
|
}
|
|
3926
|
-
const rule$
|
|
4058
|
+
const rule$c = createRule$9({
|
|
3927
4059
|
create(context) {
|
|
3928
4060
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
|
|
3929
4061
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -3966,7 +4098,7 @@ const rule$b = createRule$8({
|
|
|
3966
4098
|
name: 'no-side-effects-in-computed',
|
|
3967
4099
|
});
|
|
3968
4100
|
|
|
3969
|
-
const rule$
|
|
4101
|
+
const rule$b = createUntrackedRule({
|
|
3970
4102
|
create(context) {
|
|
3971
4103
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
3972
4104
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -4012,7 +4144,7 @@ const rule$a = createUntrackedRule({
|
|
|
4012
4144
|
name: 'no-signal-reads-after-await-in-reactive-context',
|
|
4013
4145
|
});
|
|
4014
4146
|
|
|
4015
|
-
const createRule$
|
|
4147
|
+
const createRule$8 = ESLintUtils.RuleCreator((name) => name);
|
|
4016
4148
|
function collectParts(node) {
|
|
4017
4149
|
if (node.type === AST_NODE_TYPES.BinaryExpression && node.operator === '+') {
|
|
4018
4150
|
return [...collectParts(node.left), ...collectParts(node.right)];
|
|
@@ -4062,7 +4194,7 @@ function templateContent(template, renderExpr) {
|
|
|
4062
4194
|
: ''}`)
|
|
4063
4195
|
.join('');
|
|
4064
4196
|
}
|
|
4065
|
-
const rule$
|
|
4197
|
+
const rule$a = createRule$8({
|
|
4066
4198
|
create(context) {
|
|
4067
4199
|
const { sourceCode } = context;
|
|
4068
4200
|
let parserServices = null;
|
|
@@ -4394,7 +4526,7 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
|
|
|
4394
4526
|
}
|
|
4395
4527
|
return dedent(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
|
|
4396
4528
|
}
|
|
4397
|
-
const rule$
|
|
4529
|
+
const rule$9 = createUntrackedRule({
|
|
4398
4530
|
create(context) {
|
|
4399
4531
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
4400
4532
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -4522,7 +4654,7 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
|
|
|
4522
4654
|
});
|
|
4523
4655
|
return found;
|
|
4524
4656
|
}
|
|
4525
|
-
const rule$
|
|
4657
|
+
const rule$8 = createUntrackedRule({
|
|
4526
4658
|
create(context) {
|
|
4527
4659
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
4528
4660
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -4604,8 +4736,8 @@ const rule$7 = createUntrackedRule({
|
|
|
4604
4736
|
name: 'no-useless-untracked',
|
|
4605
4737
|
});
|
|
4606
4738
|
|
|
4607
|
-
const createRule$
|
|
4608
|
-
const rule$
|
|
4739
|
+
const createRule$7 = ESLintUtils.RuleCreator((name) => name);
|
|
4740
|
+
const rule$7 = createRule$7({
|
|
4609
4741
|
create(context, [{ printWidth }]) {
|
|
4610
4742
|
const sourceCode = context.sourceCode;
|
|
4611
4743
|
const getLineEndIndex = (lineStartIndex) => {
|
|
@@ -4857,7 +4989,7 @@ const rule$6 = createRule$6({
|
|
|
4857
4989
|
name: 'object-single-line',
|
|
4858
4990
|
});
|
|
4859
4991
|
|
|
4860
|
-
const createRule$
|
|
4992
|
+
const createRule$6 = ESLintUtils.RuleCreator((name) => name);
|
|
4861
4993
|
const EMPTY_ARGUMENT = '__EMPTY_ARGUMENT__';
|
|
4862
4994
|
function isSupportedControlFlowStatement(node) {
|
|
4863
4995
|
return (node.type === AST_NODE_TYPES.BreakStatement ||
|
|
@@ -4926,7 +5058,7 @@ function renderTest(node, sourceCode) {
|
|
|
4926
5058
|
const text = sourceCode.getText(node);
|
|
4927
5059
|
return needsParenthesesInOrChain(node) ? `(${text})` : text;
|
|
4928
5060
|
}
|
|
4929
|
-
const rule$
|
|
5061
|
+
const rule$6 = createRule$6({
|
|
4930
5062
|
create(context) {
|
|
4931
5063
|
const { sourceCode } = context;
|
|
4932
5064
|
function checkBody(statements) {
|
|
@@ -5006,8 +5138,8 @@ const rule$5 = createRule$5({
|
|
|
5006
5138
|
|
|
5007
5139
|
const MESSAGE_ID$1 = 'prefer-deep-imports';
|
|
5008
5140
|
const ERROR_MESSAGE = 'Import via root entry point is prohibited when nested entry points exist';
|
|
5009
|
-
const createRule$
|
|
5010
|
-
var preferDeepImports = createRule$
|
|
5141
|
+
const createRule$5 = ESLintUtils.RuleCreator(() => ERROR_MESSAGE);
|
|
5142
|
+
var preferDeepImports = createRule$5({
|
|
5011
5143
|
create(context, [options]) {
|
|
5012
5144
|
const allowedPackages = normalizeImportFilter(options.importFilter);
|
|
5013
5145
|
const isStrictMode = options.strict ?? false;
|
|
@@ -5348,7 +5480,7 @@ function buildRewrittenImports(node, baseImportPath, symbolToEntryPoint) {
|
|
|
5348
5480
|
return importStatements.join('\n');
|
|
5349
5481
|
}
|
|
5350
5482
|
|
|
5351
|
-
const createRule$
|
|
5483
|
+
const createRule$4 = ESLintUtils.RuleCreator((name) => name);
|
|
5352
5484
|
function getPushCall(node) {
|
|
5353
5485
|
if (node.expression.type !== AST_NODE_TYPES.CallExpression) {
|
|
5354
5486
|
return null;
|
|
@@ -5363,7 +5495,7 @@ function getPushCall(node) {
|
|
|
5363
5495
|
}
|
|
5364
5496
|
return call;
|
|
5365
5497
|
}
|
|
5366
|
-
const rule$
|
|
5498
|
+
const rule$5 = createRule$4({
|
|
5367
5499
|
create(context) {
|
|
5368
5500
|
const { sourceCode } = context;
|
|
5369
5501
|
function checkBody(statements) {
|
|
@@ -5441,6 +5573,53 @@ const rule$4 = createRule$3({
|
|
|
5441
5573
|
name: 'prefer-multi-arg-push',
|
|
5442
5574
|
});
|
|
5443
5575
|
|
|
5576
|
+
const createRule$3 = ESLintUtils.RuleCreator((name) => name);
|
|
5577
|
+
function getModuleKeywordToken(sourceCode, node) {
|
|
5578
|
+
const firstToken = sourceCode.getFirstToken(node);
|
|
5579
|
+
if (!firstToken) {
|
|
5580
|
+
return null;
|
|
5581
|
+
}
|
|
5582
|
+
if (firstToken.value === 'declare') {
|
|
5583
|
+
return sourceCode.getTokenAfter(firstToken) ?? null;
|
|
5584
|
+
}
|
|
5585
|
+
return firstToken;
|
|
5586
|
+
}
|
|
5587
|
+
const rule$4 = createRule$3({
|
|
5588
|
+
create(context) {
|
|
5589
|
+
const { sourceCode } = context;
|
|
5590
|
+
return {
|
|
5591
|
+
TSModuleDeclaration(node) {
|
|
5592
|
+
if (node.kind !== 'module' ||
|
|
5593
|
+
node.global ||
|
|
5594
|
+
node.id.type === AST_NODE_TYPES.Literal) {
|
|
5595
|
+
return;
|
|
5596
|
+
}
|
|
5597
|
+
const moduleKeywordToken = getModuleKeywordToken(sourceCode, node);
|
|
5598
|
+
if (moduleKeywordToken?.value !== 'module') {
|
|
5599
|
+
return;
|
|
5600
|
+
}
|
|
5601
|
+
context.report({
|
|
5602
|
+
fix: (fixer) => fixer.replaceText(moduleKeywordToken, 'namespace'),
|
|
5603
|
+
messageId: 'useNamespaceKeyword',
|
|
5604
|
+
node: moduleKeywordToken,
|
|
5605
|
+
});
|
|
5606
|
+
},
|
|
5607
|
+
};
|
|
5608
|
+
},
|
|
5609
|
+
meta: {
|
|
5610
|
+
docs: {
|
|
5611
|
+
description: 'Prefer `namespace Foo {}` over the older `module Foo {}` syntax for TypeScript namespace declarations.',
|
|
5612
|
+
},
|
|
5613
|
+
fixable: 'code',
|
|
5614
|
+
messages: {
|
|
5615
|
+
useNamespaceKeyword: 'Use `namespace` instead of `module` for TypeScript namespace declarations.',
|
|
5616
|
+
},
|
|
5617
|
+
schema: [],
|
|
5618
|
+
type: 'problem',
|
|
5619
|
+
},
|
|
5620
|
+
name: 'prefer-namespace-keyword',
|
|
5621
|
+
});
|
|
5622
|
+
|
|
5444
5623
|
/**
|
|
5445
5624
|
* prefer-untracked-incidental-signal-reads
|
|
5446
5625
|
*
|
|
@@ -6223,28 +6402,31 @@ const plugin = {
|
|
|
6223
6402
|
'class-property-naming': classPropertyNaming,
|
|
6224
6403
|
'decorator-key-sort': config$3,
|
|
6225
6404
|
'flat-exports': flatExports,
|
|
6226
|
-
'host-attributes-sort': rule$
|
|
6405
|
+
'host-attributes-sort': rule$n,
|
|
6227
6406
|
'html-logical-properties': config$2,
|
|
6228
|
-
'injection-token-description': rule$
|
|
6229
|
-
'no-
|
|
6407
|
+
'injection-token-description': rule$m,
|
|
6408
|
+
'no-commonjs-import-patterns': rule$l,
|
|
6409
|
+
'no-deep-imports': rule$k,
|
|
6230
6410
|
'no-deep-imports-to-indexed-packages': noDeepImportsToIndexedPackages,
|
|
6231
|
-
'no-fully-untracked-effect': rule$
|
|
6411
|
+
'no-fully-untracked-effect': rule$j,
|
|
6232
6412
|
'no-href-with-router-link': config$1,
|
|
6233
|
-
'no-implicit-public': rule$
|
|
6234
|
-
'no-
|
|
6235
|
-
'no-
|
|
6236
|
-
'no-
|
|
6413
|
+
'no-implicit-public': rule$i,
|
|
6414
|
+
'no-import-assertions': rule$h,
|
|
6415
|
+
'no-infinite-loop': rule$g,
|
|
6416
|
+
'no-legacy-peer-deps': rule$f,
|
|
6417
|
+
'no-playwright-empty-fill': rule$e,
|
|
6237
6418
|
'no-project-as-in-ng-template': config,
|
|
6238
|
-
'no-redundant-type-annotation': rule$
|
|
6239
|
-
'no-side-effects-in-computed': rule$
|
|
6240
|
-
'no-signal-reads-after-await-in-reactive-context': rule$
|
|
6241
|
-
'no-string-literal-concat': rule$
|
|
6242
|
-
'no-untracked-outside-reactive-context': rule$
|
|
6243
|
-
'no-useless-untracked': rule$
|
|
6244
|
-
'object-single-line': rule$
|
|
6245
|
-
'prefer-combined-if-control-flow': rule$
|
|
6419
|
+
'no-redundant-type-annotation': rule$d,
|
|
6420
|
+
'no-side-effects-in-computed': rule$c,
|
|
6421
|
+
'no-signal-reads-after-await-in-reactive-context': rule$b,
|
|
6422
|
+
'no-string-literal-concat': rule$a,
|
|
6423
|
+
'no-untracked-outside-reactive-context': rule$9,
|
|
6424
|
+
'no-useless-untracked': rule$8,
|
|
6425
|
+
'object-single-line': rule$7,
|
|
6426
|
+
'prefer-combined-if-control-flow': rule$6,
|
|
6246
6427
|
'prefer-deep-imports': preferDeepImports,
|
|
6247
|
-
'prefer-multi-arg-push': rule$
|
|
6428
|
+
'prefer-multi-arg-push': rule$5,
|
|
6429
|
+
'prefer-namespace-keyword': rule$4,
|
|
6248
6430
|
'prefer-untracked-incidental-signal-reads': rule$3,
|
|
6249
6431
|
'prefer-untracked-signal-getter': rule$2,
|
|
6250
6432
|
'short-tui-imports': rule$1,
|
package/package.json
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
type MessageId = 'avoidCallableNamespaceImport' | 'avoidImportEquals';
|
|
3
|
+
export declare const rule: ESLintUtils.RuleModule<MessageId, [], unknown, ESLintUtils.RuleListener> & {
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
export default rule;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
type MessageId = 'forLoop' | 'whileLoop';
|
|
2
|
+
type MessageId = 'doWhileLoop' | 'forLoop' | 'whileLoop';
|
|
3
3
|
export declare const rule: ESLintUtils.RuleModule<MessageId, [], unknown, ESLintUtils.RuleListener> & {
|
|
4
4
|
name: string;
|
|
5
5
|
};
|