Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: import-js/eslint-import-resolver-typescript
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.2.1
Choose a base ref
...
head repository: import-js/eslint-import-resolver-typescript
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.3.0
Choose a head ref
  • 2 commits
  • 15 files changed
  • 2 contributors

Commits on Sep 1, 2020

  1. Copy the full SHA
    5340f96 View commit details
  2. chore(release): 2.3.0

    JounQin committed Sep 1, 2020
    Copy the full SHA
    b2db8e3 View commit details
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.3.0](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/compare/v2.2.1...v2.3.0) (2020-09-01)


### Features

* import with .js and .jsx file extensions ([#56](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/issues/56)) ([5340f96](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/commit/5340f969fad38165f8cfb28025a5e15233d0e6f9))

### [2.2.1](https://github.com/alexgorbatchev/eslint-import-resolver-typescript/compare/v2.2.0...v2.2.1) (2020-08-14)


13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-import-resolver-typescript",
"version": "2.2.1",
"version": "2.3.0",
"description": "TypeScript .ts .tsx module resolver for `eslint-plugin-import`.",
"repository": "https://github.com/alexgorbatchev/eslint-import-resolver-typescript",
"author": "Alex Gorbatchev <alex.gorbatchev@gmail.com>",
@@ -40,6 +40,7 @@
"test": "run-p test:*",
"test:multipleEslintrcs": "eslint --ext ts,tsx tests/multipleEslintrcs",
"test:multipleTsconfigs": "eslint --ext ts,tsx tests/multipleTsconfigs",
"test:withJsExtension": "node tests/withJsExtension/test.js && eslint --ext ts,tsx tests/withJsExtension",
"test:withPaths": "eslint --ext ts,tsx tests/withPaths",
"test:withoutPaths": "eslint --ext ts,tsx tests/withoutPaths",
"type-coverage": "type-coverage --cache --detail --ignore-catch --strict --update"
@@ -60,7 +61,7 @@
"@types/debug": "^4.1.5",
"@types/glob": "^7.1.3",
"@types/is-glob": "^4.0.1",
"@types/node": "^14.0.27",
"@types/node": "^14.6.2",
"@types/resolve": "^1.17.1",
"@types/unist": "^2.0.3",
"dummy.js": "link:dummy.js",
@@ -69,14 +70,14 @@
"react": "^16.13.1",
"standard-version": "^8.0.2",
"type-coverage": "^2.9.0",
"typescript": "^3.9.7",
"yarn-deduplicate": "^2.1.1"
"typescript": "^4.0.2",
"yarn-deduplicate": "^3.0.0"
},
"resolutions": {
"eslint-import-resolver-typescript": "link:.",
"prettier": "^2.0.5"
"prettier": "^2.1.1"
},
"typeCoverage": {
"atLeast": 98.73
"atLeast": 99.27
}
}
45 changes: 42 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ import {
} from 'tsconfig-paths'
import { sync as globSync } from 'glob'
import isGlob from 'is-glob'
import { isCore, sync } from 'resolve'
import { isCore, sync, SyncOpts } from 'resolve'
import debug from 'debug'

const IMPORTER_NAME = 'eslint-import-resolver-typescript'
@@ -70,7 +70,7 @@ export function resolve(
// note that even if we map the path, we still need to do a final resolve
let foundNodePath: string | null | undefined
try {
foundNodePath = sync(mappedPath || source, {
foundNodePath = tsResolve(mappedPath || source, {
extensions: options.extensions || defaultExtensions,
basedir: path.dirname(path.resolve(file)),
packageFilter: options.packageFilter || packageFilterDefault,
@@ -120,6 +120,27 @@ function packageFilterDefault(pkg: Record<string, string>) {
return pkg
}

/**
* Like `sync` from `resolve` package, but considers that the module id
* could have a .js or .jsx extension.
*/
function tsResolve(id: string, opts?: SyncOpts): string {
try {
return sync(id, opts)
} catch (error) {
const idWithoutJsExt = removeJsExtension(id)
if (idWithoutJsExt !== id) {
return sync(idWithoutJsExt, opts)
}
throw error
}
}

/** Remove .js or .jsx extension from module id. */
function removeJsExtension(id: string) {
return id.replace(/\.jsx?$/, '')
}

let mappersBuildForOptions: TsResolverOptions
let mappers:
| Array<(source: string, file: string) => string | undefined>
@@ -142,6 +163,24 @@ function getMappedPath(source: string, file: string) {
return paths[0]
}

/**
* Like `createMatchPath` from `tsconfig-paths` package, but considers
* that the module id could have a .js or .jsx extension.
*/
const createExtendedMatchPath: typeof createMatchPath = (...createArgs) => {
const matchPath = createMatchPath(...createArgs)

return (id, ...otherArgs) => {
const match = matchPath(id, ...otherArgs)
if (match != null) return match

const idWithoutJsExt = removeJsExtension(id)
if (idWithoutJsExt !== id) {
return matchPath(idWithoutJsExt, ...otherArgs)
}
}
}

function initMappers(options: TsResolverOptions) {
if (mappers && mappersBuildForOptions === options) {
return
@@ -175,7 +214,7 @@ function initMappers(options: TsResolverOptions) {
// eslint-disable-next-line unicorn/no-fn-reference-in-iterator
.filter(isConfigLoaderSuccessResult)
.map(configLoaderResult => {
const matchPath = createMatchPath(
const matchPath = createExtendedMatchPath(
configLoaderResult.absoluteBaseUrl,
configLoaderResult.paths,
)
18 changes: 18 additions & 0 deletions tests/withJsExtension/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-env node */
/* eslint-disable @typescript-eslint/no-var-requires */
const config = require('../baseEslintConfig')(__dirname)

module.exports = {
...config,
rules: {
...config.rules,
'import/extensions': [
2,
'ignorePackages',
{
ts: 'never',
tsx: 'never',
},
],
},
}
1 change: 1 addition & 0 deletions tests/withJsExtension/bar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'bar'
3 changes: 3 additions & 0 deletions tests/withJsExtension/dtsImportee.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare const content: 'yes'

export default content
1 change: 1 addition & 0 deletions tests/withJsExtension/foo.js/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo.js'
1 change: 1 addition & 0 deletions tests/withJsExtension/foo.jsx/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo.jsx'
1 change: 1 addition & 0 deletions tests/withJsExtension/foo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo'
33 changes: 33 additions & 0 deletions tests/withJsExtension/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// import relative
import './tsImportee.js'
import './tsxImportee.jsx'
import './dtsImportee.js'
import './dtsImportee.jsx'
import './foo'
import './foo.js'
import './foo.jsx'
import './bar'

// import using tsconfig.json path mapping
import '#/tsImportee.js'
import '#/tsxImportee.jsx'
import '#/dtsImportee.js'
import '#/dtsImportee.jsx'
import '#/foo'
import '#/foo.js'
import '#/foo.jsx'
import '#/bar'

// import using tsconfig.json base url
import 'tsImportee.js'
import 'tsxImportee.jsx'
import 'dtsImportee.js'
import 'dtsImportee.jsx'
import 'foo'
import 'foo.js'
import 'foo.jsx'
import 'bar'

// import from node_module
import 'typescript/lib/typescript.js'
import 'dummy.js'
88 changes: 88 additions & 0 deletions tests/withJsExtension/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* eslint-env node */
/* eslint-disable @typescript-eslint/no-var-requires */

const path = require('path')
const assert = require('assert')

const { resolve } = require('../../')

const config = {
project: path.join(__dirname, 'tsconfig.json'),
}

const file = path.join(__dirname, 'index.ts')

function assertResolve(id, relativePath) {
const filePath = path.join(__dirname, relativePath)
assert.deepStrictEqual(resolve(id, file, config), {
found: true,
path: filePath,
})
assert.deepStrictEqual(
resolve(id, file, { ...config, alwaysTryTypes: true }),
{ found: true, path: filePath },
)
}

// import relative

assertResolve('./tsImportee.js', 'tsImportee.ts')

assertResolve('./tsxImportee.jsx', 'tsxImportee.tsx')

assertResolve('./dtsImportee.js', 'dtsImportee.d.ts')

assertResolve('./dtsImportee.jsx', 'dtsImportee.d.ts')

assertResolve('./foo', 'foo/index.ts')

assertResolve('./foo.js', 'foo.js/index.ts')

assertResolve('./foo.jsx', 'foo.jsx/index.ts')

assertResolve('./bar', 'bar/index.tsx')

// import using tsconfig.json path mapping

assertResolve('#/tsImportee.js', 'tsImportee.ts')

assertResolve('#/tsxImportee.jsx', 'tsxImportee.tsx')

assertResolve('#/dtsImportee.js', 'dtsImportee.d.ts')

assertResolve('#/dtsImportee.jsx', 'dtsImportee.d.ts')

assertResolve('#/foo', 'foo/index.ts')

assertResolve('#/foo.js', 'foo.js/index.ts')

assertResolve('#/foo.jsx', 'foo.jsx/index.ts')

assertResolve('#/bar', 'bar/index.tsx')

// import using tsconfig.json base url

assertResolve('tsImportee.js', 'tsImportee.ts')

assertResolve('tsxImportee.jsx', 'tsxImportee.tsx')

assertResolve('dtsImportee.js', 'dtsImportee.d.ts')

assertResolve('dtsImportee.jsx', 'dtsImportee.d.ts')

assertResolve('foo', 'foo/index.ts')

assertResolve('foo.js', 'foo.js/index.ts')

assertResolve('foo.jsx', 'foo.jsx/index.ts')

assertResolve('bar', 'bar/index.tsx')

// import from node_module

assertResolve(
'typescript/lib/typescript.js',
'../../node_modules/typescript/lib/typescript.js',
)

assertResolve('dummy.js', '../../node_modules/dummy.js/index.js')
1 change: 1 addition & 0 deletions tests/withJsExtension/tsImportee.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'tsImportee.ts'
10 changes: 10 additions & 0 deletions tests/withJsExtension/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"jsx": "react",
"baseUrl": "./",
"paths": {
"#/*": ["*"]
}
},
"includes": ["./**/*"]
}
1 change: 1 addition & 0 deletions tests/withJsExtension/tsxImportee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'tsxImportee.tsx'
39 changes: 22 additions & 17 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -2049,10 +2049,10 @@
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=

"@types/node@*", "@types/node@^14.0.27":
version "14.0.27"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1"
integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==
"@types/node@*", "@types/node@^14.6.2":
version "14.6.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.2.tgz#264b44c5a28dfa80198fc2f7b6d3c8a054b9491f"
integrity sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==

"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@@ -3267,6 +3267,11 @@ commander@^5.1.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==

commander@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.1.0.tgz#f8d722b78103141006b66f4c7ba1e97315ba75bc"
integrity sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==

commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -7888,10 +7893,10 @@ prettier-plugin-toml@^0.3.1:
"@toml-tools/parser" "^0.3.1"
prettier "^1.16.0"

prettier@>=1.10, prettier@^1.16.0, prettier@^1.18.2, prettier@^2.0.4, prettier@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
prettier@>=1.10, prettier@^1.16.0, prettier@^1.18.2, prettier@^2.0.4, prettier@^2.0.5, prettier@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6"
integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==

pretty-format@^26.1.0:
version "26.1.0"
@@ -10355,10 +10360,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@^3.9.7:
version "3.9.7"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
typescript@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2"
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==

uglify-js@^2.6.1:
version "2.8.29"
@@ -10873,11 +10878,11 @@ yargs@~3.10.0:
decamelize "^1.0.0"
window-size "0.1.0"

yarn-deduplicate@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-2.1.1.tgz#500a3010e4bdee3c3250936e210910c7cae3d75d"
integrity sha512-lbFJGOMnqG/ncGjNBUt+JG4qfAGqeh8o9i4i5LXqNBdQ8ov8av6T1jizWQqr+zLPLCOqp/BYBZz8FymPQSR4RA==
yarn-deduplicate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-3.0.0.tgz#e5c219c48d687e3be79eff4c719d6d7ef372f094"
integrity sha512-Ps1JEurQJ7VHt4lFD1x7QLtnsfA0DxYzdz8jvu5q7mAw8JFgRC1Hqq46uC+NjSwf2wOlitTfbmWswMnnW2Gqfg==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
commander "^5.1.0"
commander "^6.1.0"
semver "^7.3.2"