diff --git a/.size-limit.json b/.size-limit.json index 0c0657ad..648747e9 100644 --- a/.size-limit.json +++ b/.size-limit.json @@ -1,6 +1,6 @@ [ { "path": "./lib/index.js", - "limit": "3kB" + "limit": "3.1kB" } ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 70319074..f2183de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 3.8.5 + +### Patch Changes + +- [#372](https://github.com/import-js/eslint-import-resolver-typescript/pull/372) [`366eeaf`](https://github.com/import-js/eslint-import-resolver-typescript/commit/366eeaf8ba87adf7c2e165b0a73406292c002ad9) Thanks [@carlocorradini](https://github.com/carlocorradini)! - fix: if file has no corresponding mapper function, apply all of them, starting with the nearest one. + ## 3.8.4 ### Patch Changes diff --git a/package.json b/package.json index c35a251a..86e53743 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-import-resolver-typescript", - "version": "3.8.4", + "version": "3.8.5", "type": "module", "description": "This plugin adds `TypeScript` support to `eslint-plugin-import`", "repository": "git+https://github.com/import-js/eslint-import-resolver-typescript", @@ -57,6 +57,7 @@ "test:importXResolverV3": "cross-env ESLINT_USE_FLAT_CONFIG=true eslint --config=tests/importXResolverV3/eslint.config.js tests/importXResolverV3", "test:multipleEslintrcs": "eslint --ext ts,tsx tests/multipleEslintrcs", "test:multipleTsconfigs": "eslint --ext ts,tsx tests/multipleTsconfigs", + "test:nearestTsconfig": "eslint --ext ts,tsx tests/nearestTsconfig", "test:withJsExtension": "node tests/withJsExtension/test.js && eslint --ext ts,tsx tests/withJsExtension", "test:withJsconfig": "eslint --ext js tests/withJsconfig", "test:withPaths": "eslint --ext ts,tsx tests/withPaths", diff --git a/src/index.ts b/src/index.ts index 1287aefe..b774b3ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -112,6 +112,7 @@ let prevCwd: string let mappersCachedOptions: InternalResolverOptions let mappers: Array<{ + path: string files: Set mapperFn: NonNullable> }> = [] @@ -311,35 +312,50 @@ function getMappedPaths( paths = [resolved] } } else { - paths = [ - ...new Set( - mappers - .filter(({ files }) => files.has(file)) - .map(({ mapperFn }) => - mapperFn(source).map(item => [ - ...extensions.map(ext => `${item}${ext}`), - ...originalExtensions.map(ext => `${item}/index${ext}`), - ]), - ) - .flat(2) - .map(toNativePathSeparator), - ), - ].filter(mappedPath => { - try { - const stat = fs.statSync(mappedPath, { throwIfNoEntry: false }) - if (stat === undefined) return false - if (stat.isFile()) return true - - // Maybe this is a module dir? - if (stat.isDirectory()) { - return isModule(mappedPath) + // Filter mapper functions associated with file + let mapperFns: Array>> = + mappers + .filter(({ files }) => files.has(file)) + .map(({ mapperFn }) => mapperFn) + if (mapperFns.length === 0) { + // If empty, try all mapper functions, starting with the nearest one + mapperFns = mappers + .map(mapper => ({ + mapperFn: mapper.mapperFn, + counter: equalChars(path.dirname(file), path.dirname(mapper.path)), + })) + .sort( + (a, b) => + // Sort in descending order where the nearest one has the longest counter + b.counter - a.counter, + ) + .map(({ mapperFn }) => mapperFn) + } + paths = mapperFns + .map(mapperFn => + mapperFn(source).map(item => [ + ...extensions.map(ext => `${item}${ext}`), + ...originalExtensions.map(ext => `${item}/index${ext}`), + ]), + ) + .flat(2) + .map(toNativePathSeparator) + .filter(mappedPath => { + try { + const stat = fs.statSync(mappedPath, { throwIfNoEntry: false }) + if (stat === undefined) return false + if (stat.isFile()) return true + + // Maybe this is a module dir? + if (stat.isDirectory()) { + return isModule(mappedPath) + } + } catch { + return false } - } catch { - return false - } - return false - }) + return false + }) } if (retry && paths.length === 0) { @@ -487,6 +503,7 @@ function initMappers(options: InternalResolverOptions) { } return { + path: toNativePathSeparator(tsconfigResult.path), files: new Set(files.map(toNativePathSeparator)), mapperFn, } @@ -551,3 +568,23 @@ function toNativePathSeparator(p: string) { function isDefined(value: T | null | undefined): value is T { return value !== null && value !== undefined } + +/** + * Counts how many characters in strings `a` and `b` are exactly the same and in the same position. + * + * @param {string} a First string + * @param {string} b Second string + * @returns Number of matching characters + */ +function equalChars(a: string, b: string): number { + if (a.length === 0 || b.length === 0) { + return 0 + } + + let i = 0 + const length = Math.min(a.length, b.length) + while (i < length && a.charAt(i) === b.charAt(i)) { + i += 1 + } + return i +} diff --git a/tests/nearestTsconfig/.eslintrc.cjs b/tests/nearestTsconfig/.eslintrc.cjs new file mode 100644 index 00000000..285ee8d6 --- /dev/null +++ b/tests/nearestTsconfig/.eslintrc.cjs @@ -0,0 +1,10 @@ +const path = require('node:path') + +const project = [ + 'tsconfig.json', + 'a/tsconfig.json', + 'a/b/tsconfig.json', + 'a/b/c/tsconfig.json', +].map(tsconfig => path.resolve(__dirname, tsconfig)) + +module.exports = require('../baseEslintConfig.cjs')(project) diff --git a/tests/nearestTsconfig/a/app/app.ts b/tests/nearestTsconfig/a/app/app.ts new file mode 100644 index 00000000..9597f5bf --- /dev/null +++ b/tests/nearestTsconfig/a/app/app.ts @@ -0,0 +1,2 @@ +import 'components/a' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/app/app.ts b/tests/nearestTsconfig/a/b/app/app.ts new file mode 100644 index 00000000..61b335ec --- /dev/null +++ b/tests/nearestTsconfig/a/b/app/app.ts @@ -0,0 +1,2 @@ +import 'components/b' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/c/app/app.ts b/tests/nearestTsconfig/a/b/c/app/app.ts new file mode 100644 index 00000000..e49cf01e --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/app/app.ts @@ -0,0 +1,2 @@ +import 'components/c' +import 'components/root' diff --git a/tests/nearestTsconfig/a/b/c/components/c.ts b/tests/nearestTsconfig/a/b/c/components/c.ts new file mode 100644 index 00000000..da4b0eda --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/components/c.ts @@ -0,0 +1 @@ +export default 'c' diff --git a/tests/nearestTsconfig/a/b/c/tsconfig.json b/tests/nearestTsconfig/a/b/c/tsconfig.json new file mode 100644 index 00000000..6f4b6a28 --- /dev/null +++ b/tests/nearestTsconfig/a/b/c/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../../../components/*", "./components/*"] + } + }, + "files": ["components/c.ts"] +} diff --git a/tests/nearestTsconfig/a/b/components/b.ts b/tests/nearestTsconfig/a/b/components/b.ts new file mode 100644 index 00000000..a3bb4904 --- /dev/null +++ b/tests/nearestTsconfig/a/b/components/b.ts @@ -0,0 +1 @@ +export default 'b' diff --git a/tests/nearestTsconfig/a/b/tsconfig.json b/tests/nearestTsconfig/a/b/tsconfig.json new file mode 100644 index 00000000..fedccddb --- /dev/null +++ b/tests/nearestTsconfig/a/b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../../components/*", "./components/*"] + } + }, + "files": ["components/b.ts"] +} diff --git a/tests/nearestTsconfig/a/components/a.ts b/tests/nearestTsconfig/a/components/a.ts new file mode 100644 index 00000000..90bd54cd --- /dev/null +++ b/tests/nearestTsconfig/a/components/a.ts @@ -0,0 +1 @@ +export default 'a' diff --git a/tests/nearestTsconfig/a/tsconfig.json b/tests/nearestTsconfig/a/tsconfig.json new file mode 100644 index 00000000..c01728fe --- /dev/null +++ b/tests/nearestTsconfig/a/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["../components/*", "./components/*"] + } + }, + "files": ["components/a.ts"] +} diff --git a/tests/nearestTsconfig/app/app.ts b/tests/nearestTsconfig/app/app.ts new file mode 100644 index 00000000..60f1cde9 --- /dev/null +++ b/tests/nearestTsconfig/app/app.ts @@ -0,0 +1 @@ +import 'components/root' diff --git a/tests/nearestTsconfig/components/root.ts b/tests/nearestTsconfig/components/root.ts new file mode 100644 index 00000000..8c841b31 --- /dev/null +++ b/tests/nearestTsconfig/components/root.ts @@ -0,0 +1 @@ +export default 'root' diff --git a/tests/nearestTsconfig/tsconfig.json b/tests/nearestTsconfig/tsconfig.json new file mode 100644 index 00000000..21cf5788 --- /dev/null +++ b/tests/nearestTsconfig/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "components/*": ["./components/*"] + } + }, + "files": ["components/root.ts"] +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy