From c7f0e0d5ea79822327bd4a8a49942d0b554dac20 Mon Sep 17 00:00:00 2001 From: Collin Sauve Date: Tue, 9 May 2017 21:11:08 -0400 Subject: [PATCH] import/extensions should have a ignorePackages option. Fixes #414 --- docs/rules/extensions.md | 26 +++++++++++++++++++++++++- src/core/importType.js | 2 +- src/rules/extensions.js | 14 +++++++++----- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/docs/rules/extensions.md b/docs/rules/extensions.md index 6ca33bb447..26a464ce9f 100644 --- a/docs/rules/extensions.md +++ b/docs/rules/extensions.md @@ -6,7 +6,7 @@ In order to provide a consistent use of file extensions across your code base, t ## Rule Details -This rule either takes one string option, one object option, or a string and an object option. If it is the string `"never"` (the default value), then the rule forbids the use for any extension. If it is the string `"always"`, then the rule enforces the use of extensions for all import statements. +This rule either takes one string option, one object option, or a string and an object option. If it is the string `"never"` (the default value), then the rule forbids the use for any extension. If it is the string `"always"`, then the rule enforces the use of extensions for all import statements. If it is the string `"ignorePackages"`, then the rule enforces the use of extensions for all import statements except package imports. By providing an object you can configure each extension separately, so for example `{ "js": "always", "json": "never" }` would always enforce the use of the `.js` extension but never allow the use of the `.json` extension. @@ -86,6 +86,30 @@ import express from 'express/index.js'; import * as path from 'path'; ``` +The following patterns are considered problems when configuration set to "ignorePackages": + +```js +import foo from './foo'; + +import bar from './bar'; + +import Component from './Component' + +``` + +The following patterns are not considered problems when configuration set to "ignorePackages": + +```js +import foo from './foo.js'; + +import bar from './bar.json'; + +import Component from './Component.jsx' + +import express from 'express'; + +``` + ## When Not To Use It If you are not concerned about a consistent usage of file extension. diff --git a/src/core/importType.js b/src/core/importType.js index 869ca7496e..199a117090 100644 --- a/src/core/importType.js +++ b/src/core/importType.js @@ -23,7 +23,7 @@ function isExternalPath(path, name, settings) { } const externalModuleRegExp = /^\w/ -function isExternalModule(name, settings, path) { +export function isExternalModule(name, settings, path) { return externalModuleRegExp.test(name) && isExternalPath(path, name, settings) } diff --git a/src/rules/extensions.js b/src/rules/extensions.js index 2036ba0555..a477517121 100644 --- a/src/rules/extensions.js +++ b/src/rules/extensions.js @@ -2,9 +2,9 @@ import path from 'path' import has from 'has' import resolve from 'eslint-module-utils/resolve' -import { isBuiltIn } from '../core/importType' +import { isBuiltIn, isExternalModule } from '../core/importType' -const enumValues = { enum: [ 'always', 'never' ] } +const enumValues = { enum: [ 'always', 'ignorePackages', 'never' ] } const patternProperties = { type: 'object', patternProperties: { '.*': enumValues }, @@ -46,9 +46,10 @@ module.exports = { typeof configuration === 'object' ? configuration : context.options[1] ) - function isUseOfExtensionRequired(extension) { + function isUseOfExtensionRequired(extension, isModule) { if (!has(modifiers, extension)) { modifiers[extension] = defaultConfig } - return modifiers[extension] === 'always' + const modifier = modifiers[extension]; + return (!isModule && modifier === 'ignorePackages') || modifier === 'always'; } function isUseOfExtensionForbidden(extension) { @@ -77,8 +78,11 @@ module.exports = { // for unresolved, use source value. const extension = path.extname(resolvedPath || importPath).substring(1) + // determine if this is a module + const isModule = isExternalModule(importPath, context.settings); + if (!extension || !importPath.endsWith(extension)) { - if (isUseOfExtensionRequired(extension) && !isUseOfExtensionForbidden(extension)) { + if (isUseOfExtensionRequired(extension, isModule) && !isUseOfExtensionForbidden(extension)) { context.report({ node: source, message: