1
1
import path from 'path' ;
2
2
3
+ import minimatch from 'minimatch' ;
3
4
import resolve from 'eslint-module-utils/resolve' ;
4
5
import { isBuiltIn , isExternalModule , isScoped } from '../core/importType' ;
5
6
import moduleVisitor from 'eslint-module-utils/moduleVisitor' ;
@@ -16,6 +17,26 @@ const properties = {
16
17
pattern : patternProperties ,
17
18
checkTypeImports : { type : 'boolean' } ,
18
19
ignorePackages : { type : 'boolean' } ,
20
+ pathGroupOverrides : {
21
+ type : 'array' ,
22
+ items : {
23
+ type : 'object' ,
24
+ properties : {
25
+ pattern : {
26
+ type : 'string' ,
27
+ } ,
28
+ patternOptions : {
29
+ type : 'object' ,
30
+ } ,
31
+ action : {
32
+ type : 'string' ,
33
+ enum : [ 'enforce' , 'ignore' ] ,
34
+ } ,
35
+ } ,
36
+ additionalProperties : false ,
37
+ required : [ 'pattern' , 'action' ] ,
38
+ } ,
39
+ }
19
40
} ,
20
41
} ;
21
42
@@ -54,6 +75,10 @@ function buildProperties(context) {
54
75
if ( obj . checkTypeImports !== undefined ) {
55
76
result . checkTypeImports = obj . checkTypeImports ;
56
77
}
78
+
79
+ if ( obj . pathGroupOverrides !== undefined ) {
80
+ result . pathGroupOverrides = obj . pathGroupOverrides ;
81
+ }
57
82
} ) ;
58
83
59
84
if ( result . defaultConfig === 'ignorePackages' ) {
@@ -143,20 +168,37 @@ module.exports = {
143
168
return false ;
144
169
}
145
170
171
+ function computeOverrideAction ( pathGroupOverrides = [ ] , path ) {
172
+ for ( let i = 0 , l = pathGroupOverrides . length ; i < l ; i ++ ) {
173
+ const { pattern, patternOptions, action } = pathGroupOverrides [ i ] ;
174
+ if ( minimatch ( path , pattern , patternOptions || { nocomment : true } ) ) {
175
+ return action ;
176
+ }
177
+ }
178
+ }
179
+
146
180
function checkFileExtension ( source , node ) {
147
181
// bail if the declaration doesn't have a source, e.g. "export { foo };", or if it's only partially typed like in an editor
148
182
if ( ! source || ! source . value ) { return ; }
149
183
150
184
const importPathWithQueryString = source . value ;
151
185
186
+ // If not undefined, the user decided if rules are enforced on this import
187
+ const overrideAction = computeOverrideAction (
188
+ props . pathGroupOverrides ,
189
+ importPathWithQueryString
190
+ ) ;
191
+
192
+ if ( overrideAction === 'ignore' ) { return ; }
193
+
152
194
// don't enforce anything on builtins
153
- if ( isBuiltIn ( importPathWithQueryString , context . settings ) ) { return ; }
195
+ if ( ! overrideAction && isBuiltIn ( importPathWithQueryString , context . settings ) ) { return ; }
154
196
155
197
const importPath = importPathWithQueryString . replace ( / \? ( .* ) $ / , '' ) ;
156
198
157
199
// don't enforce in root external packages as they may have names with `.js`.
158
200
// Like `import Decimal from decimal.js`)
159
- if ( isExternalRootModule ( importPath ) ) { return ; }
201
+ if ( ! overrideAction && isExternalRootModule ( importPath ) ) { return ; }
160
202
161
203
const resolvedPath = resolve ( importPath , context ) ;
162
204
@@ -174,7 +216,7 @@ module.exports = {
174
216
if ( ! extension || ! importPath . endsWith ( `.${ extension } ` ) ) {
175
217
// ignore type-only imports and exports
176
218
if ( ! props . checkTypeImports && ( node . importKind === 'type' || node . exportKind === 'type' ) ) { return ; }
177
- const extensionRequired = isUseOfExtensionRequired ( extension , isPackage ) ;
219
+ const extensionRequired = isUseOfExtensionRequired ( extension , ! overrideAction && isPackage ) ;
178
220
const extensionForbidden = isUseOfExtensionForbidden ( extension ) ;
179
221
if ( extensionRequired && ! extensionForbidden ) {
180
222
context . report ( {
0 commit comments