@taiga-ui/eslint-plugin-experience-next 0.459.0 → 0.460.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 +57 -0
- package/index.d.ts +4 -1
- package/index.esm.js +149 -25
- package/package.json +6 -6
- package/rules/no-project-as-in-ng-template.d.ts +3 -0
- package/rules/no-redundant-type-annotation.d.ts +6 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ export default [
|
|
|
49
49
|
| no-href-with-router-link | Do not use href and routerLink attributes together on the same element | | 🔧 | |
|
|
50
50
|
| no-implicit-public | Require explicit `public` modifier for class members and parameter properties | ✅ | 🔧 | |
|
|
51
51
|
| no-playwright-empty-fill | Enforce `clear()` over `fill('')` in Playwright tests | ✅ | 🔧 | |
|
|
52
|
+
| no-project-as-in-ng-template | `ngProjectAs` has no effect inside `<ng-template>` or dynamic outlets | | | |
|
|
52
53
|
| no-redundant-type-annotation | Disallow redundant type annotations when the type is already inferred from the initializer | ✅ | 🔧 | |
|
|
53
54
|
| no-string-literal-concat | Disallow string literal concatenation; merge adjacent literals into one | ✅ | 🔧 | |
|
|
54
55
|
| object-single-line | Enforce single-line formatting for single-property objects when it fits `printWidth` | ✅ | 🔧 | |
|
|
@@ -285,6 +286,36 @@ await page.getByLabel('Name').clear();
|
|
|
285
286
|
|
|
286
287
|
---
|
|
287
288
|
|
|
289
|
+
## no-project-as-in-ng-template
|
|
290
|
+
|
|
291
|
+
`ngProjectAs` has no effect when the element is inside an `<ng-template>`, `*ngTemplateOutlet`, `*ngComponentOutlet`, or
|
|
292
|
+
`*polymorpheusOutlet`. Content instantiated through these dynamic outlets does not participate in Angular's static
|
|
293
|
+
content projection, so the attribute is silently ignored at runtime.
|
|
294
|
+
|
|
295
|
+
```html
|
|
296
|
+
<!-- ❌ error — inside <ng-template> -->
|
|
297
|
+
<ng-template #tpl>
|
|
298
|
+
<div ngProjectAs="[someSlot]">content</div>
|
|
299
|
+
</ng-template>
|
|
300
|
+
|
|
301
|
+
<!-- ❌ error — on the outlet host itself -->
|
|
302
|
+
<ng-container
|
|
303
|
+
*ngTemplateOutlet="tpl"
|
|
304
|
+
ngProjectAs="[someSlot]"
|
|
305
|
+
></ng-container>
|
|
306
|
+
|
|
307
|
+
<!-- ❌ error — polymorpheusOutlet -->
|
|
308
|
+
<ng-container
|
|
309
|
+
*polymorpheusOutlet="content"
|
|
310
|
+
ngProjectAs="someSlot"
|
|
311
|
+
></ng-container>
|
|
312
|
+
|
|
313
|
+
<!-- ✅ ok — static content projection -->
|
|
314
|
+
<div ngProjectAs="[someSlot]">content</div>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
288
319
|
## no-string-literal-concat
|
|
289
320
|
|
|
290
321
|
Disallows concatenating string literals with `+`. Adjacent string literals are always mergeable into one — splitting
|
|
@@ -536,6 +567,32 @@ x: Animal = new Dog();
|
|
|
536
567
|
x: MyService | null = inject(MyService);
|
|
537
568
|
```
|
|
538
569
|
|
|
570
|
+
The rule does **not** report when the annotation provides contextual typing that narrows an array literal to a tuple.
|
|
571
|
+
Without the annotation TypeScript would infer `number[]` instead of the required tuple type, widening the type and
|
|
572
|
+
breaking compilation:
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
type SelectionRange = readonly [from: number, to: number];
|
|
576
|
+
interface ElementState {
|
|
577
|
+
readonly value: string;
|
|
578
|
+
readonly selection: SelectionRange;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// ✅ ok — [0, 0] is inferred as SelectionRange only because of the annotation;
|
|
582
|
+
// removing it would widen the type to ElementState | {value: string; selection: number[]}
|
|
583
|
+
const state: ElementState = flag ? {value: '', selection: [0, 0]} : existingState;
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"@taiga-ui/experience-next/no-redundant-type-annotation": ["error", {"ignoreTupleContextualTyping": true}]
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
| Option | Type | Default | Description |
|
|
593
|
+
| ----------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
|
594
|
+
| `ignoreTupleContextualTyping` | `boolean` | `true` | Preserve annotations when they provide contextual typing that narrows an array literal to a tuple type |
|
|
595
|
+
|
|
539
596
|
---
|
|
540
597
|
|
|
541
598
|
## strict-tui-doc-example
|
package/index.d.ts
CHANGED
|
@@ -40,7 +40,10 @@ declare const plugin: {
|
|
|
40
40
|
'no-playwright-empty-fill': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useClear", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
41
41
|
name: string;
|
|
42
42
|
};
|
|
43
|
-
'no-
|
|
43
|
+
'no-project-as-in-ng-template': import("eslint").Rule.RuleModule;
|
|
44
|
+
'no-redundant-type-annotation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"redundantTypeAnnotation", [({
|
|
45
|
+
ignoreTupleContextualTyping?: boolean;
|
|
46
|
+
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
44
47
|
name: string;
|
|
45
48
|
};
|
|
46
49
|
'no-string-literal-concat': import("@typescript-eslint/utils/ts-eslint").RuleModule<"flattenTemplate" | "mergeLiterals" | "useTemplate", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
package/index.esm.js
CHANGED
|
@@ -32,6 +32,7 @@ import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
|
32
32
|
import ts, { isCallExpression } from 'typescript';
|
|
33
33
|
import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from '@typescript-eslint/types';
|
|
34
34
|
import path from 'node:path';
|
|
35
|
+
import { TmplAstTemplate } from '@angular-eslint/bundled-angular-compiler';
|
|
35
36
|
|
|
36
37
|
var htmlEslint = defineConfig([
|
|
37
38
|
{
|
|
@@ -989,6 +990,7 @@ var recommended = defineConfig([
|
|
|
989
990
|
'@angular-eslint/template/prefer-control-flow': angularVersion >= modernAngularRules.preferControlFlow ? 'error' : 'off',
|
|
990
991
|
'@angular-eslint/template/prefer-self-closing-tags': 'error',
|
|
991
992
|
'@angular-eslint/template/prefer-template-literal': angularVersion >= modernAngularRules.templateLiteral ? 'error' : 'off',
|
|
993
|
+
'@taiga-ui/experience-next/no-project-as-in-ng-template': 'error',
|
|
992
994
|
},
|
|
993
995
|
},
|
|
994
996
|
{
|
|
@@ -1238,7 +1240,7 @@ function readJSON(path) {
|
|
|
1238
1240
|
}
|
|
1239
1241
|
}
|
|
1240
1242
|
|
|
1241
|
-
const config$
|
|
1243
|
+
const config$3 = {
|
|
1242
1244
|
create(context) {
|
|
1243
1245
|
const classesInFile = new Map();
|
|
1244
1246
|
return {
|
|
@@ -1397,7 +1399,7 @@ var classPropertyNaming = createRule$e({
|
|
|
1397
1399
|
name: 'class-property-naming',
|
|
1398
1400
|
});
|
|
1399
1401
|
|
|
1400
|
-
const config$
|
|
1402
|
+
const config$2 = {
|
|
1401
1403
|
create(context) {
|
|
1402
1404
|
const order = context.options[0] || {};
|
|
1403
1405
|
return {
|
|
@@ -1500,7 +1502,7 @@ function isExternalPureTuple(typeChecker, type) {
|
|
|
1500
1502
|
}
|
|
1501
1503
|
|
|
1502
1504
|
const createRule$d = ESLintUtils.RuleCreator((name) => name);
|
|
1503
|
-
const MESSAGE_ID$
|
|
1505
|
+
const MESSAGE_ID$6 = 'spreadArrays';
|
|
1504
1506
|
var flatExports = createRule$d({
|
|
1505
1507
|
create(context) {
|
|
1506
1508
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
@@ -1566,7 +1568,7 @@ var flatExports = createRule$d({
|
|
|
1566
1568
|
fix(fixer) {
|
|
1567
1569
|
return fixer.replaceText(elementNode, `...${meta.name}`);
|
|
1568
1570
|
},
|
|
1569
|
-
messageId: MESSAGE_ID$
|
|
1571
|
+
messageId: MESSAGE_ID$6,
|
|
1570
1572
|
node: elementNode,
|
|
1571
1573
|
});
|
|
1572
1574
|
}
|
|
@@ -1617,7 +1619,7 @@ var flatExports = createRule$d({
|
|
|
1617
1619
|
},
|
|
1618
1620
|
fixable: 'code',
|
|
1619
1621
|
messages: {
|
|
1620
|
-
[MESSAGE_ID$
|
|
1622
|
+
[MESSAGE_ID$6]: 'Spread "{{ name }}" to avoid nested arrays in exported entities.',
|
|
1621
1623
|
},
|
|
1622
1624
|
schema: [],
|
|
1623
1625
|
type: 'suggestion',
|
|
@@ -1625,7 +1627,7 @@ var flatExports = createRule$d({
|
|
|
1625
1627
|
name: 'flat-exports',
|
|
1626
1628
|
});
|
|
1627
1629
|
|
|
1628
|
-
const MESSAGE_ID$
|
|
1630
|
+
const MESSAGE_ID$5 = 'invalid-injection-token-description';
|
|
1629
1631
|
const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
|
|
1630
1632
|
const createRule$c = ESLintUtils.RuleCreator((name) => name);
|
|
1631
1633
|
const rule$9 = createRule$c({
|
|
@@ -1659,7 +1661,7 @@ const rule$9 = createRule$c({
|
|
|
1659
1661
|
const [start, end] = description.range;
|
|
1660
1662
|
return fixer.insertTextBeforeRange([start + 1, end], `[${name}]: `);
|
|
1661
1663
|
},
|
|
1662
|
-
messageId: MESSAGE_ID$
|
|
1664
|
+
messageId: MESSAGE_ID$5,
|
|
1663
1665
|
node: description,
|
|
1664
1666
|
});
|
|
1665
1667
|
}
|
|
@@ -1669,14 +1671,14 @@ const rule$9 = createRule$c({
|
|
|
1669
1671
|
meta: {
|
|
1670
1672
|
docs: { description: ERROR_MESSAGE$3 },
|
|
1671
1673
|
fixable: 'code',
|
|
1672
|
-
messages: { [MESSAGE_ID$
|
|
1674
|
+
messages: { [MESSAGE_ID$5]: ERROR_MESSAGE$3 },
|
|
1673
1675
|
schema: [],
|
|
1674
1676
|
type: 'problem',
|
|
1675
1677
|
},
|
|
1676
1678
|
name: 'injection-token-description',
|
|
1677
1679
|
});
|
|
1678
1680
|
|
|
1679
|
-
const MESSAGE_ID$
|
|
1681
|
+
const MESSAGE_ID$4 = 'no-deep-imports';
|
|
1680
1682
|
const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
|
|
1681
1683
|
const CODE_EXTENSIONS = new Set([
|
|
1682
1684
|
'.cjs',
|
|
@@ -1738,7 +1740,7 @@ const rule$8 = createRule$b({
|
|
|
1738
1740
|
const [start, end] = node.source.range;
|
|
1739
1741
|
return fixer.replaceTextRange([start + 1, end - 1], importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
|
|
1740
1742
|
},
|
|
1741
|
-
messageId: MESSAGE_ID$
|
|
1743
|
+
messageId: MESSAGE_ID$4,
|
|
1742
1744
|
node: node.source,
|
|
1743
1745
|
});
|
|
1744
1746
|
},
|
|
@@ -1748,7 +1750,7 @@ const rule$8 = createRule$b({
|
|
|
1748
1750
|
defaultOptions: [DEFAULT_OPTIONS],
|
|
1749
1751
|
docs: { description: ERROR_MESSAGE$2 },
|
|
1750
1752
|
fixable: 'code',
|
|
1751
|
-
messages: { [MESSAGE_ID$
|
|
1753
|
+
messages: { [MESSAGE_ID$4]: ERROR_MESSAGE$2 },
|
|
1752
1754
|
schema: [
|
|
1753
1755
|
{
|
|
1754
1756
|
additionalProperties: false,
|
|
@@ -1984,9 +1986,9 @@ function stripKnownExtensions(filePathOrSpecifier) {
|
|
|
1984
1986
|
return filePathOrSpecifier.replace(/\.(?:d\.ts|ts|tsx|js|jsx|mjs|cjs)$/, '');
|
|
1985
1987
|
}
|
|
1986
1988
|
|
|
1987
|
-
const MESSAGE_ID$
|
|
1989
|
+
const MESSAGE_ID$3 = 'no-href-with-router-link';
|
|
1988
1990
|
const ERROR_MESSAGE$1 = 'Do not use href and routerLink attributes together on the same element';
|
|
1989
|
-
const config = {
|
|
1991
|
+
const config$1 = {
|
|
1990
1992
|
create(context) {
|
|
1991
1993
|
return {
|
|
1992
1994
|
Tag(node) {
|
|
@@ -2014,7 +2016,7 @@ const config = {
|
|
|
2014
2016
|
fix: (fixer) => hrefAttribute?.range
|
|
2015
2017
|
? fixer.removeRange(hrefAttribute.range)
|
|
2016
2018
|
: null,
|
|
2017
|
-
messageId: MESSAGE_ID$
|
|
2019
|
+
messageId: MESSAGE_ID$3,
|
|
2018
2020
|
node: (routerLinkAttribute ??
|
|
2019
2021
|
hrefAttribute ??
|
|
2020
2022
|
htmlNode),
|
|
@@ -2026,7 +2028,7 @@ const config = {
|
|
|
2026
2028
|
meta: {
|
|
2027
2029
|
docs: { description: ERROR_MESSAGE$1 },
|
|
2028
2030
|
fixable: 'code',
|
|
2029
|
-
messages: { [MESSAGE_ID$
|
|
2031
|
+
messages: { [MESSAGE_ID$3]: ERROR_MESSAGE$1 },
|
|
2030
2032
|
type: 'problem',
|
|
2031
2033
|
},
|
|
2032
2034
|
};
|
|
@@ -2191,11 +2193,115 @@ function isPlaywrightLocatorType(type) {
|
|
|
2191
2193
|
});
|
|
2192
2194
|
}
|
|
2193
2195
|
|
|
2196
|
+
const MESSAGE_ID$2 = 'no-project-as-in-ng-template';
|
|
2197
|
+
const NESTED_TEMPLATE_MESSAGE_ID = 'no-nested-template-in-dynamic-outlet';
|
|
2198
|
+
const PROJECT_AS_ERROR_MESSAGE = 'ngProjectAs on a dynamic outlet breaks SSR hydration. Use static content projection instead.';
|
|
2199
|
+
const NESTED_TEMPLATE_ERROR_MESSAGE = 'Avoid nesting ng-template inside dynamic outlet containers. Move the template outside the ng-container.';
|
|
2200
|
+
const DYNAMIC_OUTLET_DIRECTIVES = new Set([
|
|
2201
|
+
'ngComponentOutlet',
|
|
2202
|
+
'ngTemplateOutlet',
|
|
2203
|
+
'polymorpheusOutlet',
|
|
2204
|
+
]);
|
|
2205
|
+
function toLoc(span) {
|
|
2206
|
+
return {
|
|
2207
|
+
end: {
|
|
2208
|
+
column: span.end.col,
|
|
2209
|
+
line: span.end.line + 1,
|
|
2210
|
+
},
|
|
2211
|
+
start: {
|
|
2212
|
+
column: span.start.col,
|
|
2213
|
+
line: span.start.line + 1,
|
|
2214
|
+
},
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
function isInsideDynamicOutlet(node) {
|
|
2218
|
+
let parent = node.parent;
|
|
2219
|
+
while (parent) {
|
|
2220
|
+
const hasDynamicOutletDirective = parent instanceof TmplAstTemplate &&
|
|
2221
|
+
parent.templateAttrs.some((attr) => DYNAMIC_OUTLET_DIRECTIVES.has(attr.name));
|
|
2222
|
+
if (hasDynamicOutletDirective) {
|
|
2223
|
+
return true;
|
|
2224
|
+
}
|
|
2225
|
+
parent = parent.parent;
|
|
2226
|
+
}
|
|
2227
|
+
return false;
|
|
2228
|
+
}
|
|
2229
|
+
function checkProjectAsOnDynamicOutlet(context, node) {
|
|
2230
|
+
const ngProjectAsAttr = node.attributes.find((attr) => attr.name === 'ngProjectAs') ??
|
|
2231
|
+
node.inputs.find((input) => input.name === 'ngProjectAs');
|
|
2232
|
+
if (ngProjectAsAttr && isInsideDynamicOutlet(node)) {
|
|
2233
|
+
context.report({
|
|
2234
|
+
loc: toLoc(ngProjectAsAttr.sourceSpan),
|
|
2235
|
+
messageId: MESSAGE_ID$2,
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
function checkNestedTemplateInDynamicOutlet(context, node) {
|
|
2240
|
+
const hasDynamicOutletInput = node.inputs.some((input) => DYNAMIC_OUTLET_DIRECTIVES.has(input.name));
|
|
2241
|
+
if (!hasDynamicOutletInput) {
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
for (const child of node.children) {
|
|
2245
|
+
if (child instanceof TmplAstTemplate && child.tagName === 'ng-template') {
|
|
2246
|
+
context.report({
|
|
2247
|
+
loc: toLoc(child.sourceSpan),
|
|
2248
|
+
messageId: NESTED_TEMPLATE_MESSAGE_ID,
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
const config = {
|
|
2254
|
+
create(context) {
|
|
2255
|
+
return {
|
|
2256
|
+
Element(rawNode) {
|
|
2257
|
+
const node = rawNode;
|
|
2258
|
+
checkProjectAsOnDynamicOutlet(context, node);
|
|
2259
|
+
checkNestedTemplateInDynamicOutlet(context, node);
|
|
2260
|
+
},
|
|
2261
|
+
};
|
|
2262
|
+
},
|
|
2263
|
+
meta: {
|
|
2264
|
+
docs: { description: PROJECT_AS_ERROR_MESSAGE },
|
|
2265
|
+
messages: {
|
|
2266
|
+
[MESSAGE_ID$2]: PROJECT_AS_ERROR_MESSAGE,
|
|
2267
|
+
[NESTED_TEMPLATE_MESSAGE_ID]: NESTED_TEMPLATE_ERROR_MESSAGE,
|
|
2268
|
+
},
|
|
2269
|
+
schema: [],
|
|
2270
|
+
type: 'problem',
|
|
2271
|
+
},
|
|
2272
|
+
};
|
|
2273
|
+
|
|
2194
2274
|
const createRule$7 = ESLintUtils.RuleCreator((name) => name);
|
|
2275
|
+
function collectArrayExpressions(node) {
|
|
2276
|
+
const result = [];
|
|
2277
|
+
if (node.type === AST_NODE_TYPES.ArrayExpression) {
|
|
2278
|
+
result.push(node);
|
|
2279
|
+
}
|
|
2280
|
+
switch (node.type) {
|
|
2281
|
+
case AST_NODE_TYPES.BinaryExpression:
|
|
2282
|
+
case AST_NODE_TYPES.LogicalExpression:
|
|
2283
|
+
result.push(...collectArrayExpressions(node.left));
|
|
2284
|
+
result.push(...collectArrayExpressions(node.right));
|
|
2285
|
+
break;
|
|
2286
|
+
case AST_NODE_TYPES.ConditionalExpression:
|
|
2287
|
+
result.push(...collectArrayExpressions(node.consequent));
|
|
2288
|
+
result.push(...collectArrayExpressions(node.alternate));
|
|
2289
|
+
break;
|
|
2290
|
+
case AST_NODE_TYPES.ObjectExpression:
|
|
2291
|
+
for (const property of node.properties) {
|
|
2292
|
+
if (property.type === AST_NODE_TYPES.Property) {
|
|
2293
|
+
result.push(...collectArrayExpressions(property.value));
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
break;
|
|
2297
|
+
}
|
|
2298
|
+
return result;
|
|
2299
|
+
}
|
|
2195
2300
|
const rule$5 = createRule$7({
|
|
2196
2301
|
create(context) {
|
|
2197
2302
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
2198
2303
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
2304
|
+
const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
|
|
2199
2305
|
function check(node, typeAnnotation, value) {
|
|
2200
2306
|
if (!typeAnnotation || !value) {
|
|
2201
2307
|
return;
|
|
@@ -2218,12 +2324,18 @@ const rule$5 = createRule$7({
|
|
|
2218
2324
|
!value.returnType) {
|
|
2219
2325
|
return;
|
|
2220
2326
|
}
|
|
2221
|
-
// If the
|
|
2222
|
-
//
|
|
2223
|
-
//
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2327
|
+
// If the annotation provides contextual typing that narrows an array
|
|
2328
|
+
// literal to a tuple (e.g. [0, 0] → readonly [number, number]), removing
|
|
2329
|
+
// it would widen the inferred type. This covers both direct array literals
|
|
2330
|
+
// and arrays nested inside object literals or conditional expressions.
|
|
2331
|
+
if (ignoreTupleContextualTyping) {
|
|
2332
|
+
const arrayExpressions = collectArrayExpressions(value);
|
|
2333
|
+
for (const arrayExpression of arrayExpressions) {
|
|
2334
|
+
const tsArrayNode = parserServices.esTreeNodeToTSNodeMap.get(arrayExpression);
|
|
2335
|
+
if (typeChecker.isTupleType(typeChecker.getTypeAtLocation(tsArrayNode))) {
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2227
2339
|
}
|
|
2228
2340
|
// If the initializer is a call to a generic function with no explicit
|
|
2229
2341
|
// type arguments, the type parameters may be inferred from the
|
|
@@ -2264,7 +2376,18 @@ const rule$5 = createRule$7({
|
|
|
2264
2376
|
messages: {
|
|
2265
2377
|
redundantTypeAnnotation: 'Type annotation is redundant — the type is already inferred from the initializer',
|
|
2266
2378
|
},
|
|
2267
|
-
schema: [
|
|
2379
|
+
schema: [
|
|
2380
|
+
{
|
|
2381
|
+
additionalProperties: false,
|
|
2382
|
+
properties: {
|
|
2383
|
+
ignoreTupleContextualTyping: {
|
|
2384
|
+
description: 'Preserve annotations when they provide contextual typing that narrows an array literal to a tuple type. Defaults to true.',
|
|
2385
|
+
type: 'boolean',
|
|
2386
|
+
},
|
|
2387
|
+
},
|
|
2388
|
+
type: 'object',
|
|
2389
|
+
},
|
|
2390
|
+
],
|
|
2268
2391
|
type: 'suggestion',
|
|
2269
2392
|
},
|
|
2270
2393
|
name: 'no-redundant-type-annotation',
|
|
@@ -3627,16 +3750,17 @@ const plugin = {
|
|
|
3627
3750
|
version: pkg.version,
|
|
3628
3751
|
},
|
|
3629
3752
|
rules: {
|
|
3630
|
-
'array-as-const': config$
|
|
3753
|
+
'array-as-const': config$3,
|
|
3631
3754
|
'class-property-naming': classPropertyNaming,
|
|
3632
|
-
'decorator-key-sort': config$
|
|
3755
|
+
'decorator-key-sort': config$2,
|
|
3633
3756
|
'flat-exports': flatExports,
|
|
3634
3757
|
'injection-token-description': rule$9,
|
|
3635
3758
|
'no-deep-imports': rule$8,
|
|
3636
3759
|
'no-deep-imports-to-indexed-packages': noDeepImportsToIndexedPackages,
|
|
3637
|
-
'no-href-with-router-link': config,
|
|
3760
|
+
'no-href-with-router-link': config$1,
|
|
3638
3761
|
'no-implicit-public': rule$7,
|
|
3639
3762
|
'no-playwright-empty-fill': rule$6,
|
|
3763
|
+
'no-project-as-in-ng-template': config,
|
|
3640
3764
|
'no-redundant-type-annotation': rule$5,
|
|
3641
3765
|
'no-string-literal-concat': rule$4,
|
|
3642
3766
|
'object-single-line': rule$3,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taiga-ui/eslint-plugin-experience-next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.460.0",
|
|
4
4
|
"description": "An ESLint plugin to enforce a consistent code styles across taiga-ui projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
],
|
|
28
28
|
"type": "module",
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@typescript-eslint/rule-tester": "8.58.
|
|
30
|
+
"@typescript-eslint/rule-tester": "8.58.1",
|
|
31
31
|
"glob": "13.0.6"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@eslint/compat": "^2.0.
|
|
34
|
+
"@eslint/compat": "^2.0.5",
|
|
35
35
|
"@eslint/markdown": "^8.0.1",
|
|
36
36
|
"@html-eslint/eslint-plugin": "^0.59.0",
|
|
37
37
|
"@html-eslint/parser": "^0.59.0",
|
|
38
38
|
"@smarttools/eslint-plugin-rxjs": "^1.0.22",
|
|
39
39
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
40
40
|
"@types/glob": "*",
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^8.58.
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.58.1",
|
|
42
42
|
"angular-eslint": "^20.7.0",
|
|
43
43
|
"eslint": "^9.39.2",
|
|
44
44
|
"eslint-config-prettier": "^10.1.7",
|
|
45
45
|
"eslint-plugin-compat": "^7.0.1",
|
|
46
|
-
"eslint-plugin-cypress": "^6.
|
|
46
|
+
"eslint-plugin-cypress": "^6.3.0",
|
|
47
47
|
"eslint-plugin-de-morgan": "^2.1.1",
|
|
48
48
|
"eslint-plugin-decorator-position": "^6.0.0",
|
|
49
49
|
"eslint-plugin-file-progress": "^3.0.2",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
62
62
|
"glob": "*",
|
|
63
63
|
"globals": "^17.4.0",
|
|
64
|
-
"typescript-eslint": "^8.58.
|
|
64
|
+
"typescript-eslint": "^8.58.1"
|
|
65
65
|
},
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
|
|
2
|
+
type Options = [
|
|
3
|
+
{
|
|
4
|
+
ignoreTupleContextualTyping?: boolean;
|
|
5
|
+
}?
|
|
6
|
+
];
|
|
7
|
+
export declare const rule: ESLintUtils.RuleModule<"redundantTypeAnnotation", Options, unknown, ESLintUtils.RuleListener> & {
|
|
3
8
|
name: string;
|
|
4
9
|
};
|
|
5
10
|
export default rule;
|