@taiga-ui/eslint-plugin-experience-next 0.382.0 → 0.384.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/index.d.ts CHANGED
@@ -11,29 +11,49 @@ declare const plugin: {
11
11
  };
12
12
  rules: {
13
13
  'array-as-const': import("eslint").Rule.RuleModule;
14
- 'class-property-naming': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidName", [import("./rules/class-property-naming").RuleConfig[]], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
14
+ 'class-property-naming': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalidName", [import("./rules/class-property-naming").RuleConfig[]], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
15
+ name: string;
16
+ };
15
17
  'decorator-key-sort': import("eslint").Rule.RuleModule;
16
- 'flat-exports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"spreadArrays", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
17
- 'injection-token-description': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalid-injection-token-description", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
18
+ 'flat-exports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"spreadArrays", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
19
+ name: string;
20
+ };
21
+ 'injection-token-description': import("@typescript-eslint/utils/ts-eslint").RuleModule<"invalid-injection-token-description", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
22
+ name: string;
23
+ };
18
24
  'no-deep-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"no-deep-imports", [{
19
25
  currentProject: string;
20
26
  deepImport: string;
21
27
  ignoreImports: string[];
22
28
  importDeclaration: string;
23
29
  projectName: string;
24
- }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
25
- 'no-deep-imports-to-indexed-packages': import("@typescript-eslint/utils/ts-eslint").RuleModule<"deepImport", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
30
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
31
+ name: string;
32
+ };
33
+ 'no-deep-imports-to-indexed-packages': import("@typescript-eslint/utils/ts-eslint").RuleModule<"deepImport", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
34
+ name: string;
35
+ };
26
36
  'no-href-with-router-link': import("eslint").Rule.RuleModule;
27
- 'no-implicit-public': import("@typescript-eslint/utils/ts-eslint").RuleModule<"implicitPublic", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
37
+ 'no-implicit-public': import("@typescript-eslint/utils/ts-eslint").RuleModule<"implicitPublic", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
38
+ name: string;
39
+ };
28
40
  'prefer-deep-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"prefer-deep-imports", [{
29
41
  importFilter: string[] | string;
30
42
  strict?: boolean;
31
- }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
32
- 'short-tui-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"replaceTuiImport", import("./rules/short-tui-imports").Options, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
43
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
44
+ name: string;
45
+ };
46
+ 'short-tui-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"replaceTuiImport", import("./rules/short-tui-imports").Options, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
47
+ name: string;
48
+ };
33
49
  'standalone-imports-sort': import("@typescript-eslint/utils/ts-eslint").RuleModule<"incorrectOrder", [{
34
50
  decorators?: string[];
35
- }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
36
- 'strict-tui-doc-example': import("@typescript-eslint/utils/ts-eslint").RuleModule<"strict-doc-example-extensions-invalid-key" | "strict-doc-example-extensions-invalid-value", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
51
+ }], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
52
+ name: string;
53
+ };
54
+ 'strict-tui-doc-example': import("@typescript-eslint/utils/ts-eslint").RuleModule<"strict-doc-example-extensions-invalid-key" | "strict-doc-example-extensions-invalid-value", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
55
+ name: string;
56
+ };
37
57
  };
38
58
  };
39
59
  export { TUI_RECOMMENDED_NAMING_CONVENTION } from './rules/convention';
package/index.esm.js CHANGED
@@ -1435,7 +1435,7 @@ function isArray(node) {
1435
1435
  }
1436
1436
 
1437
1437
  function getConstArray(node) {
1438
- if (!node || node.type !== AST_NODE_TYPES$1.TSAsExpression) {
1438
+ if (node?.type !== AST_NODE_TYPES$1.TSAsExpression) {
1439
1439
  return null;
1440
1440
  }
1441
1441
  const annotation = node.typeAnnotation;
@@ -1522,8 +1522,7 @@ var flatExports = createRule$8({
1522
1522
  return;
1523
1523
  }
1524
1524
  const elementNode = arr.node.elements[index];
1525
- if (!elementNode ||
1526
- elementNode.type !== AST_NODE_TYPES.Identifier) {
1525
+ if (elementNode?.type !== AST_NODE_TYPES.Identifier) {
1527
1526
  return;
1528
1527
  }
1529
1528
  const hasLocalArrayMeta = arrays.has(meta.name);
@@ -1556,7 +1555,7 @@ var flatExports = createRule$8({
1556
1555
  const elements = [];
1557
1556
  let isDirty = false;
1558
1557
  for (const el of arrayExpression.elements) {
1559
- if (!el || el.type !== AST_NODE_TYPES.Identifier) {
1558
+ if (el?.type !== AST_NODE_TYPES.Identifier) {
1560
1559
  isDirty = true;
1561
1560
  continue;
1562
1561
  }
@@ -1750,54 +1749,154 @@ var noDeepImportsToIndexedPackages = createRule$5({
1750
1749
  const parserServices = ESLintUtils.getParserServices(context);
1751
1750
  const program = parserServices.program;
1752
1751
  const compilerHost = ts.createCompilerHost(program.getCompilerOptions(), true);
1752
+ function resolveTypescriptModule(moduleSpecifier) {
1753
+ const resolved = ts.resolveModuleName(moduleSpecifier, context.filename, program.getCompilerOptions(), compilerHost);
1754
+ return resolved.resolvedModule?.resolvedFileName ?? null;
1755
+ }
1753
1756
  return {
1754
1757
  ImportDeclaration(node) {
1755
- const importPath = node.source.value;
1756
- if (typeof importPath !== 'string' || importPath.startsWith('.')) {
1758
+ const importSpecifier = node.source.value;
1759
+ if (typeof importSpecifier !== 'string') {
1757
1760
  return;
1758
1761
  }
1759
- const containingFile = context.filename;
1760
- const { resolvedModule } = ts.resolveModuleName(importPath, containingFile, program.getCompilerOptions(), compilerHost);
1761
- const resolvedPath = resolvedModule?.resolvedFileName;
1762
- if (!resolvedPath || resolvedPath.endsWith('index.ts')) {
1762
+ if (!isExternalModuleSpecifier(importSpecifier)) {
1763
1763
  return;
1764
1764
  }
1765
- const dir = path.dirname(resolvedPath);
1766
- const baseDir = path.resolve(dir, '..');
1767
- const indexPath = path.join(baseDir, 'index.ts');
1768
- const ngPackagePath = path.join(baseDir, 'ng-package.json');
1769
- const packageJsonPath = path.join(baseDir, 'package.json');
1770
- const hasIndex = fs.existsSync(indexPath);
1771
- const hasPackage = fs.existsSync(ngPackagePath) || fs.existsSync(packageJsonPath);
1772
- if (hasIndex && hasPackage) {
1773
- const relative = path.relative(baseDir, resolvedPath);
1774
- const shouldFix = !!(relative && !relative.startsWith('..'));
1775
- if (shouldFix) {
1776
- const parts = importPath.split('/');
1777
- const suggestedImport = parts.slice(0, -1).join('/');
1778
- context.report({
1779
- data: { importPath, suggestedImport },
1780
- messageId: 'deepImport',
1781
- node: node.source,
1782
- });
1783
- }
1765
+ const packageRootSpecifier = getPackageRootSpecifier(importSpecifier);
1766
+ const importSubpath = getSubpath(importSpecifier, packageRootSpecifier);
1767
+ if (!importSubpath) {
1768
+ return;
1769
+ }
1770
+ const resolvedRootModuleFilePath = resolveTypescriptModule(packageRootSpecifier);
1771
+ if (!resolvedRootModuleFilePath) {
1772
+ return;
1773
+ }
1774
+ const packageMarkerFilePath = pickPackageMarkerFile(resolvedRootModuleFilePath);
1775
+ if (!packageMarkerFilePath) {
1776
+ return;
1777
+ }
1778
+ const packageDirectory = path.dirname(packageMarkerFilePath);
1779
+ const indexFilePath = pickIndexFileInDirectory(packageDirectory);
1780
+ if (!indexFilePath) {
1781
+ return;
1782
+ }
1783
+ const hasMatchingReExport = indexExportsSubpath(indexFilePath, importSubpath);
1784
+ if (!hasMatchingReExport) {
1785
+ return;
1784
1786
  }
1787
+ context.report({
1788
+ data: {
1789
+ importPath: importSpecifier,
1790
+ suggestedImport: packageRootSpecifier,
1791
+ },
1792
+ messageId: 'deepImport',
1793
+ node: node.source,
1794
+ });
1785
1795
  },
1786
1796
  };
1787
1797
  },
1788
1798
  defaultOptions: [],
1789
1799
  meta: {
1790
1800
  docs: {
1791
- description: 'Disallow deep imports from packages that expose an index.ts next to ng-package.json or package.json',
1801
+ description: 'Disallow deep imports only when package root index.ts (or index.d.ts) re-exports that subpath, and the package is marked by ng-package.json or package.json',
1792
1802
  },
1793
1803
  messages: {
1794
- deepImport: 'Import "{{importPath}}" should go through the package index.ts (use "{{suggestedImport}}").',
1804
+ deepImport: 'Import "{{importPath}}" should go through the package root export (use "{{suggestedImport}}").',
1795
1805
  },
1796
1806
  schema: [],
1797
1807
  type: 'problem',
1798
1808
  },
1799
1809
  name: 'no-deep-imports-to-indexed-packages',
1800
1810
  });
1811
+ function isExternalModuleSpecifier(moduleSpecifier) {
1812
+ if (!moduleSpecifier || moduleSpecifier.startsWith('.')) {
1813
+ return false;
1814
+ }
1815
+ return !path.isAbsolute(moduleSpecifier);
1816
+ }
1817
+ function pickPackageMarkerFile(resolvedRootFilePath) {
1818
+ const resolvedRootDirectory = path.dirname(resolvedRootFilePath);
1819
+ const nearestNgPackageJson = findNearestFileUpwards(resolvedRootDirectory, 'ng-package.json');
1820
+ const nearestPackageJson = findNearestFileUpwards(resolvedRootDirectory, 'package.json');
1821
+ return nearestNgPackageJson ?? nearestPackageJson ?? null;
1822
+ }
1823
+ function pickIndexFileInDirectory(packageDirectory) {
1824
+ const indexTypescriptPath = path.join(packageDirectory, 'index.ts');
1825
+ const indexTypesDeclarationPath = path.join(packageDirectory, 'index.d.ts');
1826
+ if (fs.existsSync(indexTypescriptPath)) {
1827
+ return indexTypescriptPath;
1828
+ }
1829
+ if (fs.existsSync(indexTypesDeclarationPath)) {
1830
+ return indexTypesDeclarationPath;
1831
+ }
1832
+ return null;
1833
+ }
1834
+ function isScopedPackage(importSpecifier) {
1835
+ return importSpecifier.startsWith('@');
1836
+ }
1837
+ function getPackageRootSpecifier(importSpecifier) {
1838
+ const pathParts = importSpecifier.split('/');
1839
+ if (isScopedPackage(importSpecifier)) {
1840
+ if (pathParts.length >= 2) {
1841
+ return `${pathParts[0]}/${pathParts[1]}`;
1842
+ }
1843
+ return importSpecifier;
1844
+ }
1845
+ return pathParts[0] ?? importSpecifier;
1846
+ }
1847
+ function getSubpath(importSpecifier, packageRootSpecifier) {
1848
+ if (importSpecifier === packageRootSpecifier) {
1849
+ return null;
1850
+ }
1851
+ if (!importSpecifier.startsWith(`${packageRootSpecifier}/`)) {
1852
+ return null;
1853
+ }
1854
+ return importSpecifier.slice(packageRootSpecifier.length + 1);
1855
+ }
1856
+ function findNearestFileUpwards(startDirectory, fileName) {
1857
+ let currentDirectory = startDirectory;
1858
+ while (currentDirectory.length > 0) {
1859
+ const candidatePath = path.join(currentDirectory, fileName);
1860
+ if (fs.existsSync(candidatePath)) {
1861
+ return candidatePath;
1862
+ }
1863
+ const parentDirectory = path.dirname(currentDirectory);
1864
+ if (parentDirectory === currentDirectory) {
1865
+ break;
1866
+ }
1867
+ currentDirectory = parentDirectory;
1868
+ }
1869
+ return null;
1870
+ }
1871
+ function normalizeModuleSpecifier(moduleSpecifier) {
1872
+ return moduleSpecifier.replaceAll('\\', '/');
1873
+ }
1874
+ function stripKnownExtensions(filePathOrSpecifier) {
1875
+ return filePathOrSpecifier.replace(/\.(d\.ts|ts|tsx|js|jsx|mjs|cjs)$/, '');
1876
+ }
1877
+ function indexExportsSubpath(indexFilePath, subpath) {
1878
+ const fileText = fs.readFileSync(indexFilePath, 'utf8');
1879
+ const sourceFile = ts.createSourceFile(indexFilePath, fileText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
1880
+ const expectedSpecifier = normalizeModuleSpecifier(stripKnownExtensions(`./${subpath}`));
1881
+ const expectedIndexSpecifier = normalizeModuleSpecifier(stripKnownExtensions(`./${subpath}/index`));
1882
+ let isReExportFound = false;
1883
+ sourceFile.forEachChild((astNode) => {
1884
+ if (isReExportFound) {
1885
+ return;
1886
+ }
1887
+ if (ts.isExportDeclaration(astNode)) {
1888
+ const moduleSpecifierNode = astNode.moduleSpecifier;
1889
+ if (moduleSpecifierNode && ts.isStringLiteral(moduleSpecifierNode)) {
1890
+ const exportedSpecifier = normalizeModuleSpecifier(stripKnownExtensions(moduleSpecifierNode.text));
1891
+ if (exportedSpecifier === expectedSpecifier ||
1892
+ exportedSpecifier === expectedIndexSpecifier) {
1893
+ isReExportFound = true;
1894
+ }
1895
+ }
1896
+ }
1897
+ });
1898
+ return isReExportFound;
1899
+ }
1801
1900
 
1802
1901
  const MESSAGE_ID$2 = 'no-href-with-router-link';
1803
1902
  const ERROR_MESSAGE$1 = 'Do not use href and routerLink attributes together on the same element';
@@ -1806,7 +1905,7 @@ const config = {
1806
1905
  return {
1807
1906
  Tag(node) {
1808
1907
  const htmlNode = node;
1809
- if (!htmlNode?.name || htmlNode.name.toLowerCase() !== 'a') {
1908
+ if (htmlNode?.name?.toLowerCase() !== 'a') {
1810
1909
  return;
1811
1910
  }
1812
1911
  let hrefAttribute = null;
@@ -2311,7 +2410,7 @@ const rule$1 = createRule$2({
2311
2410
  return;
2312
2411
  }
2313
2412
  const [arg] = expression.arguments;
2314
- const isNotObject = !arg || arg.type !== AST_NODE_TYPES.ObjectExpression;
2413
+ const isNotObject = arg?.type !== AST_NODE_TYPES.ObjectExpression;
2315
2414
  if (isNotObject) {
2316
2415
  return;
2317
2416
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@taiga-ui/eslint-plugin-experience-next",
3
- "version": "0.382.0",
3
+ "version": "0.384.0",
4
4
  "description": "An ESLint plugin to enforce a consistent code styles across taiga-ui projects",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "devDependencies": {
8
- "@typescript-eslint/rule-tester": "8.50.0",
8
+ "@typescript-eslint/rule-tester": "8.53.0",
9
9
  "glob": "13.0.0"
10
10
  },
11
11
  "peerDependencies": {
@@ -16,7 +16,7 @@
16
16
  "@smarttools/eslint-plugin-rxjs": "^1.0.22",
17
17
  "@stylistic/eslint-plugin": "^5.6.1",
18
18
  "@types/glob": "*",
19
- "@typescript-eslint/eslint-plugin": "^8.50.0",
19
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
20
20
  "angular-eslint": "^20.7.0",
21
21
  "eslint": "^9.39.2",
22
22
  "eslint-config-prettier": "^10.1.7",
@@ -28,7 +28,7 @@
28
28
  "eslint-plugin-jest": "^29.5.0",
29
29
  "eslint-plugin-package-json": "^0.85.0",
30
30
  "eslint-plugin-perfectionist": "^4.15.1",
31
- "eslint-plugin-playwright": "^2.4.0",
31
+ "eslint-plugin-playwright": "^2.5.0",
32
32
  "eslint-plugin-prettier": "^5.5.4",
33
33
  "eslint-plugin-promise": "^7.2.1",
34
34
  "eslint-plugin-simple-import-sort": "^12.1.1",
@@ -4,5 +4,7 @@ export interface RuleConfig {
4
4
  newFieldName: string;
5
5
  withTypesSpecifier: string[];
6
6
  }
7
- declare const _default: ESLintUtils.RuleModule<"invalidName", [RuleConfig[]], unknown, ESLintUtils.RuleListener>;
7
+ declare const _default: ESLintUtils.RuleModule<"invalidName", [RuleConfig[]], unknown, ESLintUtils.RuleListener> & {
8
+ name: string;
9
+ };
8
10
  export default _default;
@@ -1,3 +1,5 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
- declare const _default: ESLintUtils.RuleModule<"spreadArrays", [], unknown, ESLintUtils.RuleListener>;
2
+ declare const _default: ESLintUtils.RuleModule<"spreadArrays", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
3
5
  export default _default;
@@ -1,3 +1,5 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
- export declare const rule: ESLintUtils.RuleModule<"invalid-injection-token-description", [], unknown, ESLintUtils.RuleListener>;
2
+ export declare const rule: ESLintUtils.RuleModule<"invalid-injection-token-description", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
3
5
  export default rule;
@@ -1,3 +1,5 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
- declare const _default: ESLintUtils.RuleModule<"deepImport", [], unknown, ESLintUtils.RuleListener>;
2
+ declare const _default: ESLintUtils.RuleModule<"deepImport", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
3
5
  export default _default;
@@ -5,5 +5,7 @@ export declare const rule: ESLintUtils.RuleModule<"no-deep-imports", [{
5
5
  ignoreImports: string[];
6
6
  importDeclaration: string;
7
7
  projectName: string;
8
- }], unknown, ESLintUtils.RuleListener>;
8
+ }], unknown, ESLintUtils.RuleListener> & {
9
+ name: string;
10
+ };
9
11
  export default rule;
@@ -1,3 +1,5 @@
1
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
- export declare const rule: ESLintUtils.RuleModule<"implicitPublic", [], unknown, ESLintUtils.RuleListener>;
2
+ export declare const rule: ESLintUtils.RuleModule<"implicitPublic", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
3
5
  export default rule;
@@ -18,5 +18,7 @@ type RuleOptions = [
18
18
  strict?: boolean;
19
19
  }
20
20
  ];
21
- declare const _default: ESLintUtils.RuleModule<"prefer-deep-imports", RuleOptions, unknown, ESLintUtils.RuleListener>;
21
+ declare const _default: ESLintUtils.RuleModule<"prefer-deep-imports", RuleOptions, unknown, ESLintUtils.RuleListener> & {
22
+ name: string;
23
+ };
22
24
  export default _default;
@@ -11,5 +11,7 @@ export type Options = [
11
11
  ];
12
12
  export type MessageIds = 'replaceTuiImport';
13
13
  export declare const MESSAGE_ID: MessageIds;
14
- export declare const rule: ESLintUtils.RuleModule<"replaceTuiImport", Options, unknown, ESLintUtils.RuleListener>;
14
+ export declare const rule: ESLintUtils.RuleModule<"replaceTuiImport", Options, unknown, ESLintUtils.RuleListener> & {
15
+ name: string;
16
+ };
15
17
  export default rule;
@@ -2,5 +2,7 @@ import { ESLintUtils } from '@typescript-eslint/utils';
2
2
  type Options = [{
3
3
  decorators?: string[];
4
4
  }];
5
- declare const _default: ESLintUtils.RuleModule<"incorrectOrder", Options, unknown, ESLintUtils.RuleListener>;
5
+ declare const _default: ESLintUtils.RuleModule<"incorrectOrder", Options, unknown, ESLintUtils.RuleListener> & {
6
+ name: string;
7
+ };
6
8
  export default _default;
@@ -2,5 +2,7 @@ import { ESLintUtils } from '@typescript-eslint/utils';
2
2
  declare const INVALID_KEY_MESSAGE_ID: "strict-doc-example-extensions-invalid-key";
3
3
  declare const INVALID_VALUE_MESSAGE_ID: "strict-doc-example-extensions-invalid-value";
4
4
  type MessageIds = typeof INVALID_KEY_MESSAGE_ID | typeof INVALID_VALUE_MESSAGE_ID;
5
- export declare const rule: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener>;
5
+ export declare const rule: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
6
+ name: string;
7
+ };
6
8
  export default rule;