@dword-design/eslint-plugin-import-alias 5.1.2 → 6.0.3

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 CHANGED
@@ -3,49 +3,49 @@
3
3
  <!-- /TITLE -->
4
4
 
5
5
  <!-- BADGES/ -->
6
- <p>
7
- <a href="https://npmjs.org/package/@dword-design/eslint-plugin-import-alias">
8
- <img
9
- src="https://img.shields.io/npm/v/@dword-design/eslint-plugin-import-alias.svg"
10
- alt="npm version"
11
- >
12
- </a><img src="https://img.shields.io/badge/os-linux%20%7C%C2%A0macos%20%7C%C2%A0windows-blue" alt="Linux macOS Windows compatible"><a href="https://github.com/dword-design/eslint-plugin-import-alias/actions">
13
- <img
14
- src="https://github.com/dword-design/eslint-plugin-import-alias/workflows/build/badge.svg"
15
- alt="Build status"
16
- >
17
- </a><a href="https://codecov.io/gh/dword-design/eslint-plugin-import-alias">
18
- <img
19
- src="https://codecov.io/gh/dword-design/eslint-plugin-import-alias/branch/master/graph/badge.svg"
20
- alt="Coverage status"
21
- >
22
- </a><a href="https://david-dm.org/dword-design/eslint-plugin-import-alias">
23
- <img src="https://img.shields.io/david/dword-design/eslint-plugin-import-alias" alt="Dependency status">
24
- </a><img src="https://img.shields.io/badge/renovate-enabled-brightgreen" alt="Renovate enabled"><br/><a href="https://gitpod.io/#https://github.com/dword-design/eslint-plugin-import-alias">
25
- <img
26
- src="https://gitpod.io/button/open-in-gitpod.svg"
27
- alt="Open in Gitpod"
28
- width="114"
29
- >
30
- </a><a href="https://www.buymeacoffee.com/dword">
31
- <img
32
- src="https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-2.svg"
33
- alt="Buy Me a Coffee"
34
- width="114"
35
- >
36
- </a><a href="https://paypal.me/SebastianLandwehr">
37
- <img
38
- src="https://sebastianlandwehr.com/images/paypal.svg"
39
- alt="PayPal"
40
- width="163"
41
- >
42
- </a><a href="https://www.patreon.com/dworddesign">
43
- <img
44
- src="https://sebastianlandwehr.com/images/patreon.svg"
45
- alt="Patreon"
46
- width="163"
47
- >
48
- </a>
6
+ <p>
7
+ <a href="https://npmjs.org/package/@dword-design/eslint-plugin-import-alias">
8
+ <img
9
+ src="https://img.shields.io/npm/v/@dword-design/eslint-plugin-import-alias.svg"
10
+ alt="npm version"
11
+ >
12
+ </a><img src="https://img.shields.io/badge/os-linux%20%7C%C2%A0macos%20%7C%C2%A0windows-blue" alt="Linux macOS Windows compatible"><a href="https://github.com/dword-design/eslint-plugin-import-alias/actions">
13
+ <img
14
+ src="https://github.com/dword-design/eslint-plugin-import-alias/workflows/build/badge.svg"
15
+ alt="Build status"
16
+ >
17
+ </a><a href="https://codecov.io/gh/dword-design/eslint-plugin-import-alias">
18
+ <img
19
+ src="https://codecov.io/gh/dword-design/eslint-plugin-import-alias/branch/master/graph/badge.svg"
20
+ alt="Coverage status"
21
+ >
22
+ </a><a href="https://david-dm.org/dword-design/eslint-plugin-import-alias">
23
+ <img src="https://img.shields.io/david/dword-design/eslint-plugin-import-alias" alt="Dependency status">
24
+ </a><img src="https://img.shields.io/badge/renovate-enabled-brightgreen" alt="Renovate enabled"><br/><a href="https://gitpod.io/#https://github.com/dword-design/eslint-plugin-import-alias">
25
+ <img
26
+ src="https://gitpod.io/button/open-in-gitpod.svg"
27
+ alt="Open in Gitpod"
28
+ width="114"
29
+ >
30
+ </a><a href="https://www.buymeacoffee.com/dword">
31
+ <img
32
+ src="https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-2.svg"
33
+ alt="Buy Me a Coffee"
34
+ width="114"
35
+ >
36
+ </a><a href="https://paypal.me/SebastianLandwehr">
37
+ <img
38
+ src="https://sebastianlandwehr.com/images/paypal.svg"
39
+ alt="PayPal"
40
+ width="163"
41
+ >
42
+ </a><a href="https://www.patreon.com/dworddesign">
43
+ <img
44
+ src="https://sebastianlandwehr.com/images/patreon.svg"
45
+ alt="Patreon"
46
+ width="163"
47
+ >
48
+ </a>
49
49
  </p>
50
50
  <!-- /BADGES -->
51
51
 
@@ -56,15 +56,15 @@ An ESLint plugin that enforces the use of import aliases. Also supports autofixi
56
56
  Aliases are a great thing to make imports more readable and you do not have to change import paths that often when a file path is changed.
57
57
 
58
58
  ```js
59
- import foo from '../../model/sub/foo'
60
- import bar from '../other/bar'
59
+ import foo from '../../model/sub/foo';
60
+ import bar from '../other/bar';
61
61
  ```
62
62
 
63
63
  changes to
64
64
 
65
65
  ```js
66
- import foo from '@/model/sub/foo'
67
- import bar from '@/sub/other/bar'
66
+ import foo from '@/model/sub/foo';
67
+ import bar from '@/sub/other/bar';
68
68
  ```
69
69
 
70
70
  Now what if you are in a bigger team or you have a lot of projects to update. Or you just want to make sure that everything is consistent. This is where a linter comes into the play. This rule allows you to detect inconsistent imports and even autofix them. This works by matching alias paths agains the imports and replacing the import paths with the first matching aliased path.
@@ -85,12 +85,13 @@ $ yarn add @dword-design/eslint-plugin-import-alias
85
85
 
86
86
  Add the plugin to your ESLint config:
87
87
 
88
- ```json
89
- {
90
- "extends": [
91
- "plugin:@dword-design/import-alias/recommended"
92
- ],
93
- }
88
+ ```js
89
+ import { defineConfig } from 'eslint/config';
90
+ import importAlias from '@dword-design/import-alias';
91
+
92
+ export default defineConfig([
93
+ importAlias.configs.recommended,
94
+ ]);
94
95
  ```
95
96
 
96
97
  Alright, now you have to tell the plugin which aliases to use. In the simplest case, you are already using [babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver) for your aliases. Your babel config would look something like this:
package/dist/index.js CHANGED
@@ -1,14 +1,10 @@
1
- import preferAlias from "./rules/prefer-alias.js";
1
+ import preferAlias from './rules/prefer-alias.js';
2
+ const plugin = { rules: { 'prefer-alias': preferAlias } };
2
3
  export default {
3
- configs: {
4
- recommended: {
5
- plugins: ['@dword-design/import-alias'],
6
- rules: {
7
- '@dword-design/import-alias/prefer-alias': 'error'
8
- }
9
- }
10
- },
11
- rules: {
12
- 'prefer-alias': preferAlias
13
- }
14
- };
4
+ configs: {
5
+ recommended: {
6
+ plugins: { '@dword-design/import-alias': plugin },
7
+ rules: { '@dword-design/import-alias/prefer-alias': 'error' },
8
+ },
9
+ },
10
+ };
@@ -1,96 +1,87 @@
1
- import { OptionManager } from '@babel/core';
2
- import { find, keys, replace, some, startsWith } from '@dword-design/functions';
1
+ import pathLib from 'node:path';
2
+ import { loadOptions } from '@babel/core';
3
+ import defu from '@dword-design/defu';
3
4
  import { resolvePath as defaultResolvePath } from 'babel-plugin-module-resolver';
4
- import deepmerge from 'deepmerge';
5
- import P from 'path';
6
5
  const isParentImport = path => /^(\.\/)?\.\.\//.test(path);
7
6
  const findMatchingAlias = (sourcePath, currentFile, options) => {
8
- const resolvePath = options.resolvePath || defaultResolvePath;
9
- const absoluteSourcePath = P.resolve(P.dirname(currentFile), sourcePath);
10
- for (const aliasName of (_options$alias = options.alias, keys(_options$alias))) {
11
- var _options$alias, _absoluteSourcePath;
12
- const path = P.resolve(P.dirname(currentFile), resolvePath(`${aliasName}/`, currentFile, options));
13
- if (_absoluteSourcePath = absoluteSourcePath, startsWith(path)(_absoluteSourcePath)) {
14
- return {
15
- name: aliasName,
16
- path
17
- };
7
+ const resolvePath = options.resolvePath || defaultResolvePath;
8
+ const absoluteSourcePath = pathLib.resolve(pathLib.dirname(currentFile), sourcePath);
9
+ for (const aliasName of Object.keys(options.alias)) {
10
+ const path = pathLib.resolve(pathLib.dirname(currentFile), resolvePath(`${aliasName}/`, currentFile, options));
11
+ if (absoluteSourcePath.startsWith(path)) {
12
+ return { name: aliasName, path };
13
+ }
18
14
  }
19
- }
20
- return undefined;
21
15
  };
22
16
  export default {
23
- create: context => {
24
- var _babelConfig$plugins;
25
- const currentFile = context.getFilename();
26
- const folder = P.dirname(currentFile);
27
- // can't check a non-file
28
- if (currentFile === '<text>') return {};
29
- const manager = new OptionManager();
30
- const babelConfig = manager.init({
31
- filename: currentFile
32
- });
33
- const plugin = (_babelConfig$plugins = babelConfig.plugins, find({
34
- key: 'module-resolver'
35
- })(_babelConfig$plugins));
36
- const options = deepmerge.all([{
37
- alias: []
38
- }, plugin?.options || {}, context.options[0] || {}]);
39
- if (options.alias.length === 0) {
40
- throw new Error('No alias configured. You have to define aliases by either passing them to the babel-plugin-module-resolver plugin in your Babel config, or directly to the prefer-alias rule.');
41
- }
42
- const resolvePath = options.resolvePath || defaultResolvePath;
43
- return {
44
- ImportDeclaration: node => {
45
- var _ref, _options$alias2, _sourcePath2, _importWithoutAlias;
46
- const sourcePath = node.source.value;
47
- const hasAlias = (_ref = (_options$alias2 = options.alias, keys(_options$alias2)), some(alias => {
48
- var _sourcePath;
49
- return _sourcePath = sourcePath, startsWith(`${alias}/`)(_sourcePath);
50
- })(_ref));
51
-
52
- // relative parent
53
- if (_sourcePath2 = sourcePath, isParentImport(_sourcePath2)) {
54
- var _P$relative;
55
- const matchingAlias = findMatchingAlias(sourcePath, currentFile, options);
56
- if (!matchingAlias) {
57
- return undefined;
58
- }
59
- const absoluteImportPath = P.resolve(folder, sourcePath);
60
- const rewrittenImport = `${matchingAlias.name}/${_P$relative = P.relative(matchingAlias.path, absoluteImportPath), replace(/\\/g, '/')(_P$relative)}`;
61
- return context.report({
62
- fix: fixer => fixer.replaceTextRange([node.source.range[0] + 1, node.source.range[1] - 1], rewrittenImport),
63
- message: `Unexpected parent import '${sourcePath}'. Use '${rewrittenImport}' instead`,
64
- node
65
- });
17
+ create: context => {
18
+ const currentFile = context.getFilename();
19
+ const folder = pathLib.dirname(currentFile);
20
+ // can't check a non-file
21
+ if (currentFile === '<text>')
22
+ return {};
23
+ const optionsFromRule = context.options[0] ?? {};
24
+ const babelConfig = (loadOptions({
25
+ filename: currentFile,
26
+ ...optionsFromRule.babelOptions,
27
+ }) || {});
28
+ const optionsFromPlugin = babelConfig?.plugins?.find(_ => _.key === 'module-resolver')?.options ??
29
+ {};
30
+ const options = defu(optionsFromRule, optionsFromPlugin, {
31
+ alias: [],
32
+ cwd: context.cwd,
33
+ });
34
+ if (options.alias.length === 0) {
35
+ throw new Error('No alias configured. You have to define aliases by either passing them to the babel-plugin-module-resolver plugin in your Babel config, or directly to the prefer-alias rule.');
66
36
  }
67
- const importWithoutAlias = resolvePath(sourcePath, currentFile, options);
68
- if (!(_importWithoutAlias = importWithoutAlias, isParentImport(_importWithoutAlias)) && hasAlias && !options.allowSubpathWithAlias) {
69
- return context.report({
70
- fix: fixer => fixer.replaceTextRange([node.source.range[0] + 1, node.source.range[1] - 1], importWithoutAlias),
71
- message: `Unexpected subpath import via alias '${sourcePath}'. Use '${importWithoutAlias}' instead`,
72
- node
73
- });
74
- }
75
- return undefined;
76
- }
77
- };
78
- },
79
- meta: {
80
- fixable: true,
81
- schema: [{
82
- additionalProperties: false,
83
- properties: {
84
- alias: {
85
- type: 'object'
86
- },
87
- aliasForSubpaths: {
88
- default: false,
89
- type: 'boolean'
90
- }
91
- },
92
- type: 'object'
93
- }],
94
- type: 'suggestion'
95
- }
96
- };
37
+ const resolvePath = options.resolvePath || defaultResolvePath;
38
+ return {
39
+ ImportDeclaration: node => {
40
+ const sourcePath = node.source.value;
41
+ const hasAlias = Object.keys(options.alias).some(alias => sourcePath.startsWith(`${alias}/`));
42
+ // relative parent
43
+ if (isParentImport(sourcePath)) {
44
+ const matchingAlias = findMatchingAlias(sourcePath, currentFile, options);
45
+ if (!matchingAlias) {
46
+ return;
47
+ }
48
+ const absoluteImportPath = pathLib.resolve(folder, sourcePath);
49
+ const rewrittenImport = `${matchingAlias.name}/${pathLib
50
+ .relative(matchingAlias.path, absoluteImportPath)
51
+ .replaceAll('\\', '/')}`;
52
+ return context.report({
53
+ fix: fixer => fixer.replaceTextRange([node.source.range[0] + 1, node.source.range[1] - 1], rewrittenImport),
54
+ message: `Unexpected parent import '${sourcePath}'. Use '${rewrittenImport}' instead`,
55
+ node,
56
+ });
57
+ }
58
+ const importWithoutAlias = resolvePath(sourcePath, currentFile, options);
59
+ if (!isParentImport(importWithoutAlias) &&
60
+ hasAlias &&
61
+ !options.aliasForSubpaths) {
62
+ return context.report({
63
+ fix: fixer => fixer.replaceTextRange([node.source.range[0] + 1, node.source.range[1] - 1], importWithoutAlias),
64
+ message: `Unexpected subpath import via alias '${sourcePath}'. Use '${importWithoutAlias}' instead`,
65
+ node,
66
+ });
67
+ }
68
+ return;
69
+ },
70
+ };
71
+ },
72
+ meta: {
73
+ fixable: true,
74
+ schema: [
75
+ {
76
+ additionalProperties: false,
77
+ properties: {
78
+ alias: { type: 'object' },
79
+ aliasForSubpaths: { default: false, type: 'boolean' },
80
+ babelOptions: { type: 'object' },
81
+ },
82
+ type: 'object',
83
+ },
84
+ ],
85
+ type: 'suggestion',
86
+ },
87
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dword-design/eslint-plugin-import-alias",
3
- "version": "5.1.2",
3
+ "version": "6.0.3",
4
4
  "description": "An ESLint plugin that enforces the use of import aliases. Also supports autofixing.",
5
5
  "keywords": [
6
6
  "alias",
@@ -28,7 +28,8 @@
28
28
  "license": "MIT",
29
29
  "author": "Sebastian Landwehr <info@sebastianlandwehr.com>",
30
30
  "type": "module",
31
- "main": "dist/cjs-fallback.cjs",
31
+ "exports": "./dist/index.js",
32
+ "main": "dist/index.js",
32
33
  "files": [
33
34
  "dist"
34
35
  ],
@@ -43,23 +44,21 @@
43
44
  "test": "base test"
44
45
  },
45
46
  "dependencies": {
46
- "@babel/core": "^7.10.2",
47
- "@dword-design/functions": "^6.0.0",
48
- "babel-plugin-module-resolver": "^5.0.0",
49
- "deepmerge": "^4.3.1",
50
- "jiti": "^1.18.2"
47
+ "@babel/core": "^7.27.4",
48
+ "@dword-design/defu": "^1.0.0",
49
+ "babel-plugin-module-resolver": "^5.0.2"
51
50
  },
52
51
  "devDependencies": {
53
- "@dword-design/base": "^11.0.7",
54
- "@dword-design/tester": "^2.0.19",
55
- "@dword-design/tester-plugin-tmp-dir": "^2.1.26",
52
+ "@dword-design/base": "^13.0.1",
53
+ "@playwright/test": "^1.52.0",
56
54
  "depcheck-package-name": "^3.0.1",
57
- "eslint": "^8.0.0",
58
- "execa": "^9.3.1",
59
- "fs-extra": "^11.1.1",
60
- "output-files": "^2.0.0"
55
+ "endent": "npm:@dword-design/endent@^1.4.1",
56
+ "eslint": "^9.28.0",
57
+ "lodash-es": "^4.17.21",
58
+ "output-files": "^2.0.32",
59
+ "typescript-eslint": "^8.33.1"
61
60
  },
62
- "packageManager": "pnpm@9.7.1+sha512.faf344af2d6ca65c4c5c8c2224ea77a81a5e8859cbc4e06b1511ddce2f0151512431dd19e6aff31f2c6a8f5f2aced9bd2273e1fed7dd4de1868984059d2c4247",
61
+ "packageManager": "pnpm@10.11.1+sha512.e519b9f7639869dc8d5c3c5dfef73b3f091094b0a006d7317353c72b124e80e1afd429732e28705ad6bfa1ee879c1fce46c128ccebd3192101f43dd67c667912",
63
62
  "engines": {
64
63
  "node": ">=18"
65
64
  },
@@ -1,4 +0,0 @@
1
- const jiti = require('jiti')(__filename, { interopDefault: true })
2
- const api = jiti('.')
3
-
4
- module.exports = api