@taiga-ui/eslint-plugin-experience-next 0.504.0 → 0.506.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 +1 -0
- package/index.d.ts +3 -0
- package/index.esm.js +195 -88
- package/package.json +1 -1
- package/rules/recommended/prefer-loose-null-check.d.ts +4 -0
package/README.md
CHANGED
|
@@ -109,6 +109,7 @@ from third-party plugins. The exact severities and file globs live in
|
|
|
109
109
|
| [object-single-line](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/object-single-line.md) | Enforce single-line formatting for single-property objects when it fits `printWidth` | ✅ | 🔧 | |
|
|
110
110
|
| [prefer-combined-if-control-flow](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-combined-if-control-flow.md) | Combine consecutive `if` statements that use the same `return`, `break`, `continue`, or `throw` | ✅ | 🔧 | |
|
|
111
111
|
| [prefer-deep-imports](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-deep-imports.md) | Allow deep imports of Taiga UI packages | | 🔧 | |
|
|
112
|
+
| [prefer-loose-null-check](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-loose-null-check.md) | Prefer loose null checks over paired strict comparisons against `null` and `undefined` | ✅ | 🔧 | |
|
|
112
113
|
| [prefer-multi-arg-push](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-multi-arg-push.md) | Combine consecutive `.push()` calls on the same array into a single multi-argument call | ✅ | 🔧 | |
|
|
113
114
|
| [prefer-namespace-keyword](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-namespace-keyword.md) | Replace `module Foo {}` with `namespace Foo {}` for TypeScript namespace declarations | ✅ | 🔧 | |
|
|
114
115
|
| [prefer-untracked-incidental-signal-reads](https://github.com/taiga-family/toolkit/tree/main/projects/eslint-plugin-experience-next/docs/prefer-untracked-incidental-signal-reads.md) | Wrap likely-incidental signal reads with `untracked()` in reactive callbacks | ✅ | 🔧 | |
|
package/index.d.ts
CHANGED
|
@@ -148,6 +148,9 @@ declare const plugin: {
|
|
|
148
148
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
149
149
|
name: string;
|
|
150
150
|
};
|
|
151
|
+
'prefer-loose-null-check': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferLooseNullCheck", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
152
|
+
name: string;
|
|
153
|
+
};
|
|
151
154
|
'prefer-multi-arg-push': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferMultiArgPush", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
152
155
|
name: string;
|
|
153
156
|
};
|
package/index.esm.js
CHANGED
|
@@ -1213,6 +1213,7 @@ var recommended = defineConfig([
|
|
|
1213
1213
|
'@taiga-ui/experience-next/no-useless-untracked': 'error',
|
|
1214
1214
|
'@taiga-ui/experience-next/object-single-line': ['error', { printWidth: 90 }],
|
|
1215
1215
|
'@taiga-ui/experience-next/prefer-combined-if-control-flow': 'error',
|
|
1216
|
+
'@taiga-ui/experience-next/prefer-loose-null-check': 'error',
|
|
1216
1217
|
'@taiga-ui/experience-next/prefer-multi-arg-push': 'error',
|
|
1217
1218
|
'@taiga-ui/experience-next/prefer-namespace-keyword': 'error',
|
|
1218
1219
|
'@taiga-ui/experience-next/prefer-untracked-incidental-signal-reads': 'error',
|
|
@@ -1509,6 +1510,7 @@ var taigaSpecific = defineConfig([
|
|
|
1509
1510
|
{
|
|
1510
1511
|
files: pattern('**/*.html'),
|
|
1511
1512
|
ignores: [
|
|
1513
|
+
'**/proprietary/**',
|
|
1512
1514
|
// Angular ESLint virtual files for inline templates in spec/cy files
|
|
1513
1515
|
'**/*.spec.ts/**/*.html',
|
|
1514
1516
|
'**/*.cy.ts/**/*.html',
|
|
@@ -46222,7 +46224,7 @@ function buildMultilineStartTag(node, sourceText) {
|
|
|
46222
46224
|
closing,
|
|
46223
46225
|
].join('\n');
|
|
46224
46226
|
}
|
|
46225
|
-
const rule$
|
|
46227
|
+
const rule$Q = createRule({
|
|
46226
46228
|
name: 'attrs-newline',
|
|
46227
46229
|
rule: {
|
|
46228
46230
|
create(context) {
|
|
@@ -46369,7 +46371,7 @@ const config$5 = {
|
|
|
46369
46371
|
function getCorrectOrderRelative(correct, current) {
|
|
46370
46372
|
return correct.filter((item) => current.includes(item));
|
|
46371
46373
|
}
|
|
46372
|
-
const rule$
|
|
46374
|
+
const rule$P = createRule({
|
|
46373
46375
|
name: 'decorator-key-sort',
|
|
46374
46376
|
rule: config$5,
|
|
46375
46377
|
});
|
|
@@ -46433,7 +46435,7 @@ function getNodeLabel(node) {
|
|
|
46433
46435
|
}
|
|
46434
46436
|
return 'text';
|
|
46435
46437
|
}
|
|
46436
|
-
const rule$
|
|
46438
|
+
const rule$O = createRule({
|
|
46437
46439
|
name: 'element-newline',
|
|
46438
46440
|
rule: {
|
|
46439
46441
|
create(context) {
|
|
@@ -46664,7 +46666,7 @@ const PRESETS = {
|
|
|
46664
46666
|
$VUE: ['$CLASS', '$ID', '$VUE_ATTRIBUTE'],
|
|
46665
46667
|
$VUE_ATTRIBUTE: /^v-/,
|
|
46666
46668
|
};
|
|
46667
|
-
const rule$
|
|
46669
|
+
const rule$N = createRule({
|
|
46668
46670
|
create(context, [options]) {
|
|
46669
46671
|
const sourceCode = context.sourceCode;
|
|
46670
46672
|
const settings = {
|
|
@@ -46778,7 +46780,7 @@ function getHostAttributeProperties(hostObject) {
|
|
|
46778
46780
|
return null;
|
|
46779
46781
|
}
|
|
46780
46782
|
const name = getStaticPropertyName(property.key);
|
|
46781
|
-
if (name
|
|
46783
|
+
if (name == null) {
|
|
46782
46784
|
return null;
|
|
46783
46785
|
}
|
|
46784
46786
|
properties.push({ name, node: property });
|
|
@@ -46997,7 +46999,7 @@ const config$4 = {
|
|
|
46997
46999
|
type: 'suggestion',
|
|
46998
47000
|
},
|
|
46999
47001
|
};
|
|
47000
|
-
const rule$
|
|
47002
|
+
const rule$M = createRule({
|
|
47001
47003
|
name: 'html-logical-properties',
|
|
47002
47004
|
rule: config$4,
|
|
47003
47005
|
});
|
|
@@ -248249,7 +248251,7 @@ function isImportUsedOnlyAsAngularDiFirstArg(node, sourceCode) {
|
|
|
248249
248251
|
}
|
|
248250
248252
|
return hasSafeRuntimeUsage;
|
|
248251
248253
|
}
|
|
248252
|
-
const rule$
|
|
248254
|
+
const rule$L = createRule({
|
|
248253
248255
|
create(context) {
|
|
248254
248256
|
const { checker, esTreeNodeToTSNodeMap, sourceCode, tsProgram } = getTypeAwareRuleContext(context);
|
|
248255
248257
|
const checkCycles = context.options[0]?.checkCycles ?? true;
|
|
@@ -248441,21 +248443,21 @@ const rule$K = createRule({
|
|
|
248441
248443
|
getExcessParentPathReplacement(moduleSpecifierPath, resolved.resolvedFileName));
|
|
248442
248444
|
}
|
|
248443
248445
|
function checkUselessPathSegments(source) {
|
|
248444
|
-
if (!shouldCheckUselessPathSegments ||
|
|
248446
|
+
if (!shouldCheckUselessPathSegments ||
|
|
248447
|
+
!source.value.startsWith('.') ||
|
|
248448
|
+
splitModuleSpecifierQuery(source.value).query) {
|
|
248445
248449
|
return;
|
|
248446
248450
|
}
|
|
248447
|
-
const
|
|
248448
|
-
const proposedPath = getUselessPathSegmentsReplacement(parts.path);
|
|
248451
|
+
const proposedPath = getUselessPathSegmentsReplacement(source.value);
|
|
248449
248452
|
if (!proposedPath) {
|
|
248450
248453
|
return;
|
|
248451
248454
|
}
|
|
248452
|
-
const proposedModuleSpecifier = `${proposedPath}${parts.query}`;
|
|
248453
248455
|
context.report({
|
|
248454
248456
|
data: {
|
|
248455
248457
|
moduleSpecifier: source.value,
|
|
248456
|
-
proposedPath
|
|
248458
|
+
proposedPath,
|
|
248457
248459
|
},
|
|
248458
|
-
fix: (fixer) => fixer.replaceText(source, quoteModuleSpecifier(source,
|
|
248460
|
+
fix: (fixer) => fixer.replaceText(source, quoteModuleSpecifier(source, proposedPath)),
|
|
248459
248461
|
messageId: 'uselessPathSegments',
|
|
248460
248462
|
node: source,
|
|
248461
248463
|
});
|
|
@@ -248955,7 +248957,7 @@ function prependTokenName(text, name) {
|
|
|
248955
248957
|
return `${text.slice(0, 1)}[${name}]: ${text.slice(1)}`;
|
|
248956
248958
|
}
|
|
248957
248959
|
function isNgDevModeVisible(sourceCode, node) {
|
|
248958
|
-
for (let scope = sourceCode.getScope(node); scope
|
|
248960
|
+
for (let scope = sourceCode.getScope(node); scope != null; scope = scope.upper) {
|
|
248959
248961
|
if (scope.variables.some((variable) => variable.name === NG_DEV_MODE)) {
|
|
248960
248962
|
return true;
|
|
248961
248963
|
}
|
|
@@ -248975,7 +248977,7 @@ function getNgDevModeDeclarationFix(program, fixer) {
|
|
|
248975
248977
|
}
|
|
248976
248978
|
return fixer.insertTextBeforeRange([0, 0], 'declare const ngDevMode: boolean;\n');
|
|
248977
248979
|
}
|
|
248978
|
-
const rule$
|
|
248980
|
+
const rule$K = createRule({
|
|
248979
248981
|
create(context) {
|
|
248980
248982
|
const { sourceCode } = context;
|
|
248981
248983
|
const program = sourceCode.ast;
|
|
@@ -249024,7 +249026,7 @@ const rule$J = createRule({
|
|
|
249024
249026
|
name: 'injection-token-description',
|
|
249025
249027
|
});
|
|
249026
249028
|
|
|
249027
|
-
const rule$
|
|
249029
|
+
const rule$J = createRule({
|
|
249028
249030
|
create(context) {
|
|
249029
249031
|
const { sourceCode } = context;
|
|
249030
249032
|
const namespaceImports = new Map();
|
|
@@ -249119,7 +249121,7 @@ const DEFAULT_OPTIONS = {
|
|
|
249119
249121
|
importDeclaration: '^@taiga-ui*',
|
|
249120
249122
|
projectName: String.raw `(?<=^@taiga-ui/)([-\w]+)`,
|
|
249121
249123
|
};
|
|
249122
|
-
const rule$
|
|
249124
|
+
const rule$I = createRule({
|
|
249123
249125
|
create(context) {
|
|
249124
249126
|
const { currentProject, deepImport, ignoreImports, importDeclaration, projectName, } = { ...DEFAULT_OPTIONS, ...context.options[0] };
|
|
249125
249127
|
const hasNonCodeExtension = (source) => {
|
|
@@ -249211,7 +249213,7 @@ const nearestFileUpCache = new Map();
|
|
|
249211
249213
|
const markerCache = new Map();
|
|
249212
249214
|
const indexFileCache = new Map();
|
|
249213
249215
|
const indexExportsCache = new Map();
|
|
249214
|
-
const rule$
|
|
249216
|
+
const rule$H = createRule({
|
|
249215
249217
|
create(context) {
|
|
249216
249218
|
const parserServices = dist$3.ESLintUtils.getParserServices(context);
|
|
249217
249219
|
const program = parserServices.program;
|
|
@@ -249226,7 +249228,7 @@ const rule$G = createRule({
|
|
|
249226
249228
|
}
|
|
249227
249229
|
const key = `${containingDir}\0${moduleSpecifier}`;
|
|
249228
249230
|
const cachedFile = cache.get(key);
|
|
249229
|
-
if (cachedFile
|
|
249231
|
+
if (cachedFile != null) {
|
|
249230
249232
|
return cachedFile;
|
|
249231
249233
|
}
|
|
249232
249234
|
const resolved = ts.resolveModuleName(moduleSpecifier, context.filename, compilerOptions, compilerHost);
|
|
@@ -249237,7 +249239,7 @@ const rule$G = createRule({
|
|
|
249237
249239
|
function findNearestFileUpwardsCached(startDirectory, fileName) {
|
|
249238
249240
|
const key = `${startDirectory}\0${fileName}`;
|
|
249239
249241
|
const cachedPath = nearestFileUpCache.get(key);
|
|
249240
|
-
if (cachedPath
|
|
249242
|
+
if (cachedPath != null) {
|
|
249241
249243
|
return cachedPath;
|
|
249242
249244
|
}
|
|
249243
249245
|
let currentDirectory = startDirectory;
|
|
@@ -249258,7 +249260,7 @@ const rule$G = createRule({
|
|
|
249258
249260
|
}
|
|
249259
249261
|
function pickPackageMarkerFileCached(resolvedRootFilePath) {
|
|
249260
249262
|
const cachedMarker = markerCache.get(resolvedRootFilePath);
|
|
249261
|
-
if (cachedMarker
|
|
249263
|
+
if (cachedMarker != null) {
|
|
249262
249264
|
return cachedMarker;
|
|
249263
249265
|
}
|
|
249264
249266
|
const resolvedRootDirectory = path.dirname(resolvedRootFilePath);
|
|
@@ -249270,7 +249272,7 @@ const rule$G = createRule({
|
|
|
249270
249272
|
}
|
|
249271
249273
|
function pickIndexFileInDirectoryCached(packageDirectory) {
|
|
249272
249274
|
const cachedIndexFile = indexFileCache.get(packageDirectory);
|
|
249273
|
-
if (cachedIndexFile
|
|
249275
|
+
if (cachedIndexFile != null) {
|
|
249274
249276
|
return cachedIndexFile;
|
|
249275
249277
|
}
|
|
249276
249278
|
const indexTypescriptPath = path.join(packageDirectory, 'index.ts');
|
|
@@ -249408,13 +249410,13 @@ const noDuplicateAttributesRule = angular.templatePlugin.rules?.['no-duplicate-a
|
|
|
249408
249410
|
if (!noDuplicateAttributesRule) {
|
|
249409
249411
|
throw new Error('angular-eslint template rule "no-duplicate-attributes" is not available');
|
|
249410
249412
|
}
|
|
249411
|
-
const rule$
|
|
249413
|
+
const rule$G = createRule({
|
|
249412
249414
|
name: 'no-duplicate-attrs',
|
|
249413
249415
|
rule: noDuplicateAttributesRule,
|
|
249414
249416
|
});
|
|
249415
249417
|
|
|
249416
249418
|
const MESSAGE_ID$c = 'duplicateId';
|
|
249417
|
-
const rule$
|
|
249419
|
+
const rule$F = createRule({
|
|
249418
249420
|
name: 'no-duplicate-id',
|
|
249419
249421
|
rule: {
|
|
249420
249422
|
create(context) {
|
|
@@ -249476,7 +249478,7 @@ function getTrackingKey(node) {
|
|
|
249476
249478
|
}
|
|
249477
249479
|
return null;
|
|
249478
249480
|
}
|
|
249479
|
-
const rule$
|
|
249481
|
+
const rule$E = createRule({
|
|
249480
249482
|
name: 'no-duplicate-in-head',
|
|
249481
249483
|
rule: {
|
|
249482
249484
|
create(context) {
|
|
@@ -249542,7 +249544,7 @@ function getOrderedChildren(node) {
|
|
|
249542
249544
|
...node.params,
|
|
249543
249545
|
node.body,
|
|
249544
249546
|
];
|
|
249545
|
-
return children.filter((child) => child
|
|
249547
|
+
return children.filter((child) => child != null);
|
|
249546
249548
|
}
|
|
249547
249549
|
if (node.type === dist$3.AST_NODE_TYPES.BlockStatement ||
|
|
249548
249550
|
node.type === dist$3.AST_NODE_TYPES.Program) {
|
|
@@ -249569,7 +249571,7 @@ function getOrderedChildren(node) {
|
|
|
249569
249571
|
node.update,
|
|
249570
249572
|
node.body,
|
|
249571
249573
|
];
|
|
249572
|
-
return children.filter((child) => child
|
|
249574
|
+
return children.filter((child) => child != null);
|
|
249573
249575
|
}
|
|
249574
249576
|
if (node.type === dist$3.AST_NODE_TYPES.ForInStatement ||
|
|
249575
249577
|
node.type === dist$3.AST_NODE_TYPES.ForOfStatement) {
|
|
@@ -250061,7 +250063,7 @@ const ANGULAR_SIGNALS_UNTRACKED_GUIDE_URL = 'https://angular.dev/guide/signals#r
|
|
|
250061
250063
|
const ANGULAR_SIGNALS_ASYNC_GUIDE_URL = 'https://angular.dev/guide/signals#reactive-context-and-async-operations';
|
|
250062
250064
|
const createUntrackedRule = createRule;
|
|
250063
250065
|
|
|
250064
|
-
const rule$
|
|
250066
|
+
const rule$D = createUntrackedRule({
|
|
250065
250067
|
create(context) {
|
|
250066
250068
|
const { checker, esTreeNodeToTSNodeMap, program } = getTypeAwareRuleContext(context);
|
|
250067
250069
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -250134,7 +250136,7 @@ const config$3 = {
|
|
|
250134
250136
|
type: 'problem',
|
|
250135
250137
|
},
|
|
250136
250138
|
};
|
|
250137
|
-
const rule$
|
|
250139
|
+
const rule$C = createRule({
|
|
250138
250140
|
name: 'no-href-with-router-link',
|
|
250139
250141
|
rule: config$3,
|
|
250140
250142
|
});
|
|
@@ -250195,7 +250197,7 @@ function getScopeRoot(node) {
|
|
|
250195
250197
|
return (findAncestor(node, (ancestor) => ancestor.type === dist$3.AST_NODE_TYPES.Program || isFunctionLike(ancestor)) ?? node);
|
|
250196
250198
|
}
|
|
250197
250199
|
|
|
250198
|
-
const rule$
|
|
250200
|
+
const rule$B = createRule({
|
|
250199
250201
|
create(context) {
|
|
250200
250202
|
const checkImplicitPublic = (node) => {
|
|
250201
250203
|
const classRef = getEnclosingClass(node);
|
|
@@ -250257,7 +250259,7 @@ const rule$A = createRule({
|
|
|
250257
250259
|
name: 'no-implicit-public',
|
|
250258
250260
|
});
|
|
250259
250261
|
|
|
250260
|
-
const rule$
|
|
250262
|
+
const rule$A = createRule({
|
|
250261
250263
|
create(context) {
|
|
250262
250264
|
const { sourceCode } = context;
|
|
250263
250265
|
return {
|
|
@@ -250313,9 +250315,9 @@ function isInfiniteLoopLiteral(node) {
|
|
|
250313
250315
|
return unwrapped.value === true || unwrapped.value === 1;
|
|
250314
250316
|
}
|
|
250315
250317
|
function isInfiniteLoopTest(test) {
|
|
250316
|
-
return test
|
|
250318
|
+
return test == null || isInfiniteLoopLiteral(test);
|
|
250317
250319
|
}
|
|
250318
|
-
const rule$
|
|
250320
|
+
const rule$z = createRule({
|
|
250319
250321
|
create(context) {
|
|
250320
250322
|
return {
|
|
250321
250323
|
DoWhileStatement(node) {
|
|
@@ -250360,7 +250362,7 @@ const rule$y = createRule({
|
|
|
250360
250362
|
});
|
|
250361
250363
|
|
|
250362
250364
|
const LEGACY_PEER_DEPS_PATTERN = /^legacy-peer-deps\s*=\s*true$/i;
|
|
250363
|
-
const rule$
|
|
250365
|
+
const rule$y = createRule({
|
|
250364
250366
|
create(context) {
|
|
250365
250367
|
return {
|
|
250366
250368
|
Program(node) {
|
|
@@ -250820,7 +250822,7 @@ const OBSOLETE_HTML_ATTRS = {
|
|
|
250820
250822
|
};
|
|
250821
250823
|
|
|
250822
250824
|
const MESSAGE_ID$9 = 'obsolete';
|
|
250823
|
-
const rule$
|
|
250825
|
+
const rule$x = createRule({
|
|
250824
250826
|
name: 'no-obsolete-attrs',
|
|
250825
250827
|
rule: {
|
|
250826
250828
|
create(context) {
|
|
@@ -250898,7 +250900,7 @@ const OBSOLETE_HTML_TAGS = new Set([
|
|
|
250898
250900
|
]);
|
|
250899
250901
|
|
|
250900
250902
|
const MESSAGE_ID$8 = 'unexpected';
|
|
250901
|
-
const rule$
|
|
250903
|
+
const rule$w = createRule({
|
|
250902
250904
|
name: 'no-obsolete-tags',
|
|
250903
250905
|
rule: {
|
|
250904
250906
|
create(context) {
|
|
@@ -250925,7 +250927,7 @@ const rule$v = createRule({
|
|
|
250925
250927
|
},
|
|
250926
250928
|
});
|
|
250927
250929
|
|
|
250928
|
-
const rule$
|
|
250930
|
+
const rule$v = createRule({
|
|
250929
250931
|
create(context) {
|
|
250930
250932
|
const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
|
|
250931
250933
|
return {
|
|
@@ -251069,7 +251071,7 @@ const config$2 = {
|
|
|
251069
251071
|
type: 'problem',
|
|
251070
251072
|
},
|
|
251071
251073
|
};
|
|
251072
|
-
const rule$
|
|
251074
|
+
const rule$u = createRule({
|
|
251073
251075
|
name: 'no-project-as-in-ng-template',
|
|
251074
251076
|
rule: config$2,
|
|
251075
251077
|
});
|
|
@@ -251106,7 +251108,7 @@ function collectArrayExpressions(node) {
|
|
|
251106
251108
|
}
|
|
251107
251109
|
return result;
|
|
251108
251110
|
}
|
|
251109
|
-
const rule$
|
|
251111
|
+
const rule$t = createRule({
|
|
251110
251112
|
create(context) {
|
|
251111
251113
|
const { checker: typeChecker, esTreeNodeToTSNodeMap } = getTypeAwareRuleContext(context);
|
|
251112
251114
|
const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
|
|
@@ -251281,7 +251283,7 @@ function getStatementIndent(statement, sourceText) {
|
|
|
251281
251283
|
const before = sourceText.slice(lineStart, start);
|
|
251282
251284
|
return /^\s*$/.test(before) ? before : '';
|
|
251283
251285
|
}
|
|
251284
|
-
const rule$
|
|
251286
|
+
const rule$s = createRule({
|
|
251285
251287
|
create(context) {
|
|
251286
251288
|
const { checker, esTreeNodeToTSNodeMap, sourceCode } = getTypeAwareRuleContext(context);
|
|
251287
251289
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251712,7 +251714,7 @@ function inspectComputedBody(root, context, localScopes, visitedFunctions, repor
|
|
|
251712
251714
|
return;
|
|
251713
251715
|
});
|
|
251714
251716
|
}
|
|
251715
|
-
const rule$
|
|
251717
|
+
const rule$r = createRule({
|
|
251716
251718
|
create(context) {
|
|
251717
251719
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode, tsNodeToESTreeNodeMap, } = getTypeAwareRuleContext(context);
|
|
251718
251720
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251755,7 +251757,7 @@ const rule$q = createRule({
|
|
|
251755
251757
|
name: 'no-side-effects-in-computed',
|
|
251756
251758
|
});
|
|
251757
251759
|
|
|
251758
|
-
const rule$
|
|
251760
|
+
const rule$q = createUntrackedRule({
|
|
251759
251761
|
create(context) {
|
|
251760
251762
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
251761
251763
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -251849,7 +251851,7 @@ function templateContent(template, renderExpr) {
|
|
|
251849
251851
|
: ''}`)
|
|
251850
251852
|
.join('');
|
|
251851
251853
|
}
|
|
251852
|
-
const rule$
|
|
251854
|
+
const rule$p = createRule({
|
|
251853
251855
|
create(context) {
|
|
251854
251856
|
const { sourceCode } = context;
|
|
251855
251857
|
let parserServices = null;
|
|
@@ -252184,7 +252186,7 @@ function buildReactiveCallReplacement(outerUntrackedCall, reactiveCall, sourceCo
|
|
|
252184
252186
|
}
|
|
252185
252187
|
return dedent(text, reactiveCall.loc.start.column - outerUntrackedCall.parent.loc.start.column);
|
|
252186
252188
|
}
|
|
252187
|
-
const rule$
|
|
252189
|
+
const rule$o = createUntrackedRule({
|
|
252188
252190
|
create(context) {
|
|
252189
252191
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
252190
252192
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -252220,7 +252222,7 @@ const rule$n = createUntrackedRule({
|
|
|
252220
252222
|
fixer.replaceText(node, buildReactiveCallReplacement(node, reactiveCall, sourceCode)),
|
|
252221
252223
|
];
|
|
252222
252224
|
const untrackedLocalName = findUntrackedAlias(program);
|
|
252223
|
-
const stillUsed = untrackedLocalName
|
|
252225
|
+
const stillUsed = untrackedLocalName != null &&
|
|
252224
252226
|
isUntrackedUsedElsewhere(untrackedLocalName, node);
|
|
252225
252227
|
if (!stillUsed) {
|
|
252226
252228
|
fixes.push(...buildImportRemovalFixes(program, fixer, sourceCode));
|
|
@@ -252313,7 +252315,7 @@ function hasOpaqueSynchronousCalls(root, checker, esTreeNodeToTSNodeMap, program
|
|
|
252313
252315
|
});
|
|
252314
252316
|
return found;
|
|
252315
252317
|
}
|
|
252316
|
-
const rule$
|
|
252318
|
+
const rule$n = createUntrackedRule({
|
|
252317
252319
|
create(context) {
|
|
252318
252320
|
const { checker, esTreeNodeToTSNodeMap, program, sourceCode } = getTypeAwareRuleContext(context);
|
|
252319
252321
|
const signalNodeMap = esTreeNodeToTSNodeMap;
|
|
@@ -252344,11 +252346,11 @@ const rule$m = createUntrackedRule({
|
|
|
252344
252346
|
? (fixer) => {
|
|
252345
252347
|
const parentStmt = parent;
|
|
252346
252348
|
const replacement = buildReplacement(untrackedCall, parentStmt, sourceCode);
|
|
252347
|
-
if (replacement
|
|
252349
|
+
if (replacement == null) {
|
|
252348
252350
|
return null;
|
|
252349
252351
|
}
|
|
252350
252352
|
const untrackedLocalName = findUntrackedAlias(program);
|
|
252351
|
-
const stillUsed = untrackedLocalName
|
|
252353
|
+
const stillUsed = untrackedLocalName != null &&
|
|
252352
252354
|
isUntrackedUsedElsewhere(untrackedLocalName, untrackedCall);
|
|
252353
252355
|
const fixes = [fixer.replaceText(parentStmt, replacement)];
|
|
252354
252356
|
if (!stillUsed) {
|
|
@@ -252395,7 +252397,7 @@ const rule$m = createUntrackedRule({
|
|
|
252395
252397
|
name: 'no-useless-untracked',
|
|
252396
252398
|
});
|
|
252397
252399
|
|
|
252398
|
-
const rule$
|
|
252400
|
+
const rule$m = createRule({
|
|
252399
252401
|
create(context, [{ printWidth }]) {
|
|
252400
252402
|
const sourceCode = context.sourceCode;
|
|
252401
252403
|
const getLineEndIndex = (lineStartIndex) => {
|
|
@@ -252716,7 +252718,7 @@ function renderTest(node, sourceCode) {
|
|
|
252716
252718
|
const text = sourceCode.getText(node);
|
|
252717
252719
|
return needsParenthesesInOrChain(node) ? `(${text})` : text;
|
|
252718
252720
|
}
|
|
252719
|
-
const rule$
|
|
252721
|
+
const rule$l = createRule({
|
|
252720
252722
|
create(context) {
|
|
252721
252723
|
const { sourceCode } = context;
|
|
252722
252724
|
function checkBody(statements) {
|
|
@@ -252805,6 +252807,110 @@ const rule$k = createRule({
|
|
|
252805
252807
|
name: 'prefer-combined-if-control-flow',
|
|
252806
252808
|
});
|
|
252807
252809
|
|
|
252810
|
+
function parseStrictNullCheck(node, getText) {
|
|
252811
|
+
if (node.type !== dist$3.AST_NODE_TYPES.BinaryExpression) {
|
|
252812
|
+
return null;
|
|
252813
|
+
}
|
|
252814
|
+
const { left, operator, right } = node;
|
|
252815
|
+
if (operator !== '!==' && operator !== '===') {
|
|
252816
|
+
return null;
|
|
252817
|
+
}
|
|
252818
|
+
if (right.type === dist$3.AST_NODE_TYPES.Literal && right.value === null) {
|
|
252819
|
+
return { comparedWith: 'null', operand: getText(left), strictOp: operator };
|
|
252820
|
+
}
|
|
252821
|
+
if (right.type === dist$3.AST_NODE_TYPES.Identifier && right.name === 'undefined') {
|
|
252822
|
+
return { comparedWith: 'undefined', operand: getText(left), strictOp: operator };
|
|
252823
|
+
}
|
|
252824
|
+
if (left.type === dist$3.AST_NODE_TYPES.Literal && left.value === null) {
|
|
252825
|
+
return { comparedWith: 'null', operand: getText(right), strictOp: operator };
|
|
252826
|
+
}
|
|
252827
|
+
if (left.type === dist$3.AST_NODE_TYPES.Identifier && left.name === 'undefined') {
|
|
252828
|
+
return { comparedWith: 'undefined', operand: getText(right), strictOp: operator };
|
|
252829
|
+
}
|
|
252830
|
+
return null;
|
|
252831
|
+
}
|
|
252832
|
+
function isParsedNullCheck(value) {
|
|
252833
|
+
return value !== null;
|
|
252834
|
+
}
|
|
252835
|
+
function getLooseNullCheck(left, right) {
|
|
252836
|
+
if (!isParsedNullCheck(left) ||
|
|
252837
|
+
!isParsedNullCheck(right) ||
|
|
252838
|
+
left.strictOp !== right.strictOp ||
|
|
252839
|
+
left.operand !== right.operand ||
|
|
252840
|
+
left.comparedWith === right.comparedWith) {
|
|
252841
|
+
return null;
|
|
252842
|
+
}
|
|
252843
|
+
return `${left.operand} ${left.strictOp === '!==' ? '!=' : '=='} null`;
|
|
252844
|
+
}
|
|
252845
|
+
function collectAndLeaves(node) {
|
|
252846
|
+
if (node.type === dist$3.AST_NODE_TYPES.LogicalExpression && node.operator === '&&') {
|
|
252847
|
+
return [...collectAndLeaves(node.left), ...collectAndLeaves(node.right)];
|
|
252848
|
+
}
|
|
252849
|
+
return [node];
|
|
252850
|
+
}
|
|
252851
|
+
function isAndChainRoot(node) {
|
|
252852
|
+
return (node.parent.type !== dist$3.AST_NODE_TYPES.LogicalExpression ||
|
|
252853
|
+
node.parent.operator !== '&&');
|
|
252854
|
+
}
|
|
252855
|
+
function findLooseNullCheckMatch(parsedChecks) {
|
|
252856
|
+
for (const [firstCheckIndex, firstCheck] of parsedChecks.entries()) {
|
|
252857
|
+
if (!isParsedNullCheck(firstCheck)) {
|
|
252858
|
+
continue;
|
|
252859
|
+
}
|
|
252860
|
+
for (let secondCheckIndex = firstCheckIndex + 1; secondCheckIndex < parsedChecks.length; secondCheckIndex++) {
|
|
252861
|
+
const replacement = getLooseNullCheck(firstCheck, parsedChecks[secondCheckIndex] ?? null);
|
|
252862
|
+
if (replacement !== null) {
|
|
252863
|
+
return { firstCheckIndex, replacement, secondCheckIndex };
|
|
252864
|
+
}
|
|
252865
|
+
}
|
|
252866
|
+
}
|
|
252867
|
+
return null;
|
|
252868
|
+
}
|
|
252869
|
+
const rule$k = createRule({
|
|
252870
|
+
create(context) {
|
|
252871
|
+
const getText = (n) => context.sourceCode.getText(n);
|
|
252872
|
+
return {
|
|
252873
|
+
/**
|
|
252874
|
+
* Handles only paired null/undefined checks in the same `&&` chain.
|
|
252875
|
+
*/
|
|
252876
|
+
LogicalExpression(node) {
|
|
252877
|
+
if (node.operator !== '&&' || !isAndChainRoot(node)) {
|
|
252878
|
+
return;
|
|
252879
|
+
}
|
|
252880
|
+
const leaves = collectAndLeaves(node);
|
|
252881
|
+
const parsedChecks = leaves.map((leaf) => parseStrictNullCheck(leaf, getText));
|
|
252882
|
+
const match = findLooseNullCheckMatch(parsedChecks);
|
|
252883
|
+
if (match === null) {
|
|
252884
|
+
return;
|
|
252885
|
+
}
|
|
252886
|
+
const replacement = leaves
|
|
252887
|
+
.filter((_, index) => index !== match.secondCheckIndex)
|
|
252888
|
+
.map((leaf, index) => index === match.firstCheckIndex
|
|
252889
|
+
? match.replacement
|
|
252890
|
+
: getText(leaf))
|
|
252891
|
+
.join(' && ');
|
|
252892
|
+
context.report({
|
|
252893
|
+
fix: (fixer) => fixer.replaceText(node, replacement),
|
|
252894
|
+
messageId: 'preferLooseNullCheck',
|
|
252895
|
+
node,
|
|
252896
|
+
});
|
|
252897
|
+
},
|
|
252898
|
+
};
|
|
252899
|
+
},
|
|
252900
|
+
meta: {
|
|
252901
|
+
docs: {
|
|
252902
|
+
description: 'Prefer loose null checks over paired strict comparisons against `null` and `undefined`.',
|
|
252903
|
+
},
|
|
252904
|
+
fixable: 'code',
|
|
252905
|
+
messages: {
|
|
252906
|
+
preferLooseNullCheck: 'Prefer loose null check over paired strict comparisons against `null` and `undefined`.',
|
|
252907
|
+
},
|
|
252908
|
+
schema: [],
|
|
252909
|
+
type: 'suggestion',
|
|
252910
|
+
},
|
|
252911
|
+
name: 'prefer-loose-null-check',
|
|
252912
|
+
});
|
|
252913
|
+
|
|
252808
252914
|
function getPushCall(node) {
|
|
252809
252915
|
if (node.expression.type !== dist$3.AST_NODE_TYPES.CallExpression) {
|
|
252810
252916
|
return null;
|
|
@@ -253190,7 +253296,7 @@ const rule$h = createUntrackedRule({
|
|
|
253190
253296
|
const estreeNodeMap = tsNodeToESTreeNodeMap;
|
|
253191
253297
|
function buildFix(read) {
|
|
253192
253298
|
const untrackedAlias = findUntrackedAlias(program);
|
|
253193
|
-
const alreadyHasUntracked = untrackedAlias
|
|
253299
|
+
const alreadyHasUntracked = untrackedAlias != null;
|
|
253194
253300
|
const wrapped = buildUntrackedWrap(read, sourceCode, untrackedAlias ?? 'untracked');
|
|
253195
253301
|
if (alreadyHasUntracked) {
|
|
253196
253302
|
return (fixer) => [fixer.replaceText(read, wrapped)];
|
|
@@ -253520,13 +253626,13 @@ const VALID_CONTAINERS = new Set(['menu', 'ol', 'ul']);
|
|
|
253520
253626
|
*/
|
|
253521
253627
|
function isElement(node) {
|
|
253522
253628
|
return (typeof node === 'object' &&
|
|
253523
|
-
node
|
|
253629
|
+
node != null &&
|
|
253524
253630
|
typeof node['name'] === 'string' &&
|
|
253525
253631
|
Array.isArray(node['children']));
|
|
253526
253632
|
}
|
|
253527
253633
|
function getClosestParentElement(node) {
|
|
253528
253634
|
let current = node['parent'];
|
|
253529
|
-
while (current
|
|
253635
|
+
while (current != null) {
|
|
253530
253636
|
if (isElement(current)) {
|
|
253531
253637
|
return current;
|
|
253532
253638
|
}
|
|
@@ -254198,7 +254304,7 @@ const rule$6 = createRule({
|
|
|
254198
254304
|
if (!arr) {
|
|
254199
254305
|
continue;
|
|
254200
254306
|
}
|
|
254201
|
-
const elements = arr.elements.filter((el) => el
|
|
254307
|
+
const elements = arr.elements.filter((el) => el != null);
|
|
254202
254308
|
if (elements.length <= 1) {
|
|
254203
254309
|
continue;
|
|
254204
254310
|
}
|
|
@@ -254444,7 +254550,7 @@ const rule$3 = createRule({
|
|
|
254444
254550
|
const purityCache = new WeakMap();
|
|
254445
254551
|
const isPureArray = (arr) => {
|
|
254446
254552
|
const cachedPurity = purityCache.get(arr);
|
|
254447
|
-
if (cachedPurity
|
|
254553
|
+
if (cachedPurity != null) {
|
|
254448
254554
|
return cachedPurity;
|
|
254449
254555
|
}
|
|
254450
254556
|
if (arr.isDirty) {
|
|
@@ -254613,7 +254719,7 @@ const config = {
|
|
|
254613
254719
|
}
|
|
254614
254720
|
for (const attr of node.inputs) {
|
|
254615
254721
|
const attrValue = getLiteralStringValue(attr);
|
|
254616
|
-
if (attrValue
|
|
254722
|
+
if (attrValue != null) {
|
|
254617
254723
|
checkAttribute(context, attr, attrValue, checkers);
|
|
254618
254724
|
}
|
|
254619
254725
|
}
|
|
@@ -255119,42 +255225,43 @@ const plugin = {
|
|
|
255119
255225
|
},
|
|
255120
255226
|
rules: {
|
|
255121
255227
|
'array-as-const': rule$5,
|
|
255122
|
-
'attrs-newline': rule$
|
|
255228
|
+
'attrs-newline': rule$Q,
|
|
255123
255229
|
'class-property-naming': rule$4,
|
|
255124
|
-
'decorator-key-sort': rule$
|
|
255125
|
-
'element-newline': rule$
|
|
255230
|
+
'decorator-key-sort': rule$P,
|
|
255231
|
+
'element-newline': rule$O,
|
|
255126
255232
|
'flat-exports': rule$3,
|
|
255127
|
-
'host-attributes-sort': rule$
|
|
255128
|
-
'html-logical-properties': rule$
|
|
255129
|
-
'import-integrity': rule$
|
|
255130
|
-
'injection-token-description': rule$
|
|
255131
|
-
'no-commonjs-import-patterns': rule$
|
|
255132
|
-
'no-deep-imports': rule$
|
|
255133
|
-
'no-deep-imports-to-indexed-packages': rule$
|
|
255134
|
-
'no-duplicate-attrs': rule$
|
|
255135
|
-
'no-duplicate-id': rule$
|
|
255136
|
-
'no-duplicate-in-head': rule$
|
|
255137
|
-
'no-fully-untracked-effect': rule$
|
|
255138
|
-
'no-href-with-router-link': rule$
|
|
255139
|
-
'no-implicit-public': rule$
|
|
255140
|
-
'no-import-assertions': rule$
|
|
255141
|
-
'no-infinite-loop': rule$
|
|
255142
|
-
'no-legacy-peer-deps': rule$
|
|
255143
|
-
'no-obsolete-attrs': rule$
|
|
255144
|
-
'no-obsolete-tags': rule$
|
|
255145
|
-
'no-playwright-empty-fill': rule$
|
|
255146
|
-
'no-project-as-in-ng-template': rule$
|
|
255147
|
-
'no-redundant-type-annotation': rule$
|
|
255148
|
-
'no-repeated-signal-in-conditional': rule$
|
|
255233
|
+
'host-attributes-sort': rule$N,
|
|
255234
|
+
'html-logical-properties': rule$M,
|
|
255235
|
+
'import-integrity': rule$L,
|
|
255236
|
+
'injection-token-description': rule$K,
|
|
255237
|
+
'no-commonjs-import-patterns': rule$J,
|
|
255238
|
+
'no-deep-imports': rule$I,
|
|
255239
|
+
'no-deep-imports-to-indexed-packages': rule$H,
|
|
255240
|
+
'no-duplicate-attrs': rule$G,
|
|
255241
|
+
'no-duplicate-id': rule$F,
|
|
255242
|
+
'no-duplicate-in-head': rule$E,
|
|
255243
|
+
'no-fully-untracked-effect': rule$D,
|
|
255244
|
+
'no-href-with-router-link': rule$C,
|
|
255245
|
+
'no-implicit-public': rule$B,
|
|
255246
|
+
'no-import-assertions': rule$A,
|
|
255247
|
+
'no-infinite-loop': rule$z,
|
|
255248
|
+
'no-legacy-peer-deps': rule$y,
|
|
255249
|
+
'no-obsolete-attrs': rule$x,
|
|
255250
|
+
'no-obsolete-tags': rule$w,
|
|
255251
|
+
'no-playwright-empty-fill': rule$v,
|
|
255252
|
+
'no-project-as-in-ng-template': rule$u,
|
|
255253
|
+
'no-redundant-type-annotation': rule$t,
|
|
255254
|
+
'no-repeated-signal-in-conditional': rule$s,
|
|
255149
255255
|
'no-restricted-attr-values': rule$2,
|
|
255150
|
-
'no-side-effects-in-computed': rule$
|
|
255151
|
-
'no-signal-reads-after-await-in-reactive-context': rule$
|
|
255152
|
-
'no-string-literal-concat': rule$
|
|
255153
|
-
'no-untracked-outside-reactive-context': rule$
|
|
255154
|
-
'no-useless-untracked': rule$
|
|
255155
|
-
'object-single-line': rule$
|
|
255156
|
-
'prefer-combined-if-control-flow': rule$
|
|
255256
|
+
'no-side-effects-in-computed': rule$r,
|
|
255257
|
+
'no-signal-reads-after-await-in-reactive-context': rule$q,
|
|
255258
|
+
'no-string-literal-concat': rule$p,
|
|
255259
|
+
'no-untracked-outside-reactive-context': rule$o,
|
|
255260
|
+
'no-useless-untracked': rule$n,
|
|
255261
|
+
'object-single-line': rule$m,
|
|
255262
|
+
'prefer-combined-if-control-flow': rule$l,
|
|
255157
255263
|
'prefer-deep-imports': rule$1,
|
|
255264
|
+
'prefer-loose-null-check': rule$k,
|
|
255158
255265
|
'prefer-multi-arg-push': rule$j,
|
|
255159
255266
|
'prefer-namespace-keyword': rule$i,
|
|
255160
255267
|
'prefer-untracked-incidental-signal-reads': rule$h,
|
package/package.json
CHANGED