Skip to content

Commit b59c495

Browse files
committed
[Fix] make 'import/order' work in a monorepo setup with scoped modules
Fixes #1597
1 parent 72ab8ef commit b59c495

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55
This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
66

77
## [Unreleased]
8+
### Fixed
9+
- [`import/external-module-folders` setting] now correctly works with directories containing
10+
modules symlinked from `node_modules` ([#1605])
11+
12+
### Changed
13+
- [`import/external-module-folders` setting] behavior is more strict now: it will only match
14+
complete path segments. That is, `some/path` won't match `/my/awesome/path` but will still
15+
match `/my/some/path` and `/my/some/path/index.js`. Also, if an item starts with a forward
16+
slash, it will be treated as an absolute path prefix ([#1605])
817

918
## [2.20.0] - 2020-01-10
1019
### Added
@@ -638,6 +647,7 @@ for info on changes for earlier releases.
638647

639648
[`memo-parser`]: ./memo-parser/README.md
640649

650+
[#1605]: https://github.com/benmosher/eslint-plugin-import/pull/1605
641651
[#1589]: https://github.com/benmosher/eslint-plugin-import/issues/1589
642652
[#1586]: https://github.com/benmosher/eslint-plugin-import/pull/1586
643653
[#1572]: https://github.com/benmosher/eslint-plugin-import/pull/1572

README.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,26 @@ Contribution of more such shared configs for other platforms are welcome!
339339

340340
#### `import/external-module-folders`
341341

342-
An array of folders. Resolved modules only from those folders will be considered as "external". By default - `["node_modules"]`. Makes sense if you have configured your path or webpack to handle your internal paths differently and want to considered modules from some folders, for example `bower_components` or `jspm_modules`, as "external".
342+
An array of folders. Resolved modules only from those folders will be considered as "external". By default - `["node_modules"]`. Makes sense if you have configured your path or webpack to handle your internal paths differently and want to consider modules from some folders, for example `bower_components` or `jspm_modules`, as "external".
343+
344+
This option is also useful in a monorepo setup: list here all directories that contain monorepo's
345+
packages and they will be treated as external ones no matter which resolver is used.
346+
347+
Each item in this array is either a folder's name, its subpath, or its absolute prefix path:
348+
349+
- `jspm_modules` will match any file or folder named `jspm_modules` or which has a direct or
350+
non-direct parent named `jspm_modules`, e.g. `/home/me/project/jspm_modules` or
351+
`/home/me/project/jspm_modules/some-pkg/index.js`.
352+
353+
- `packages/core` will match any path that contains these two segments, for example
354+
`/home/me/project/packages/core/src/utils.js`.
355+
356+
- `/home/me/project/packages` will only match files and directories inside this directory,
357+
and the directory itself.
358+
359+
Please note that incomplete names are not allowed here so `components` won't match
360+
`bower_components` and `packages/ui` won't match `packages/ui-utils` (but will match
361+
`packages/ui/utils`).
343362

344363
#### `import/parsers`
345364

src/core/importType.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import coreModules from 'resolve/lib/core'
2-
import { join } from 'path'
32

43
import resolve from 'eslint-module-utils/resolve'
54

@@ -13,7 +12,7 @@ function baseModule(name) {
1312
}
1413

1514
export function isAbsolute(name) {
16-
return name.indexOf('/') === 0
15+
return name[0] === '/'
1716
}
1817

1918
// path is defined only when a resolver resolves to a non-standard path
@@ -26,11 +25,17 @@ export function isBuiltIn(name, settings, path) {
2625

2726
function isExternalPath(path, name, settings) {
2827
const folders = (settings && settings['import/external-module-folders']) || ['node_modules']
28+
return !path || folders.some(folder => isSubpath(folder, path))
29+
}
2930

30-
// extract the part before the first / (redux-saga/effects => redux-saga)
31-
const packageName = name.match(/([^/]+)/)[0]
31+
function isSubpath(subpath, path) {
32+
const subpathRegExpSrc = escapeRegExp(subpath.replace(/[/]$/, ''))
33+
const subpathRegExp = new RegExp(`${isAbsolute(subpath) ? '^' : '(?:^|/)'}${subpathRegExpSrc}(?:/|$)`)
34+
return subpathRegExp.test(path)
35+
}
3236

33-
return !path || folders.some(folder => -1 < path.indexOf(join(folder, packageName)))
37+
function escapeRegExp(string) {
38+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
3439
}
3540

3641
const externalModuleRegExp = /^\w/

0 commit comments

Comments
 (0)