eslint-plugin-import
eslint-plugin-import copied to clipboard
[New]: add rule `default-import-match-filename`
Closes #325 .
- Import name is considered to matche filename if they are equal after
toLowercase
, and striping extensions, and striping characters "._-". - CommonJs is also checked.
- Cases like "./", "../", are ~~not~~ now checked.
Coverage increased (+0.003%) to 97.841% when pulling 678fc02529afcf771d1a74cb57b42386721da90c on golopot:default-import-match-filename into 47f912e74eccbb6009ea5778a7cdb33e918dd495 on benmosher:master.
What does the "exception" option looks like?
// When "name" and "path" both globly match an item in whitelist, the error is ignored.
{
whitelist: [
{
name: '*', // any name is allowed
path: '*/models/*',
},
{
name: 'reactDomSever',
path: 'react-dom/sever',
},
];
}
ping @golopot, it'd be great to get this in :-)
Currently the rule is case-insesative, and underscores are ignored. Variable name foo_BarBAeZ
is allowed for file foo_bar_baz
.
https://github.com/benmosher/eslint-plugin-import/blob/dfdd7d43a06c1f449788a9921b2973c7f13e0eab/tests/src/rules/default-import-match-filename.js#L50-L53
I am having trouble in designing the option ignorePatterns
. This option is meant to ignore import statements when the import source matches a configured pattern. There are three choices:
-
(Current implementation) Use the resolved absolute path to match against the patterns. For example, in
import a from './foo'
, the source resolves to absolute path/home/me/my-project/src/foo.js
, and that path is used to match against a pattern, say**/foo.js
. In this case the pattern**/foo.js
matches. This approach has the drawback that only patterns starting with**/
can ever match, and "relative" patterns likesrc/foo.js
orfoo.js
will never match in general. -
Use the directory containing the closest
package.json
as the "cwd" for glob matching, With this approach, patternssrc/foo.js
orfoo.js
are considered to be relative to/home/me/my-project
, which is the location of the closestpackage.json
. -
Use
process.cwd
as the "cwd" for glob matching. This approach has the drawback that the lint result depends on the cwd used for running the linter.
Typically, process.cwd() is the current dir - because a rule can't know if its config came from a file (or which one), or from command line config, or an inline comment.
With option 1, however - could that resolved path have process.cwd()
stripped off it, and all patterns applied relative to that?
With option 1, however - could that resolved path have process.cwd() stripped off it, and all patterns applied relative to that?
It should be doable using the function path.relative(). That sounds like option 3 in https://github.com/benmosher/eslint-plugin-import/pull/1476#issuecomment-592915191?
Yes, option 3 sounds right to me.
Looking forward to this rule. Is there any autofix provided? Or not for now ?
It would be great to see a little bit more control over how this rule operates in the parserOptions. For example, the ability to make this case sensitive or the ability to whitelist which characters are ignored.
// These would be the defaults
{
caseSensitive: false,
allowedChars: [".", "_", "-"],
}
For example:
My repo uses absolute imports and I would like to ensure that the component is imported exactly as the filename is styled. Lets say I have a component called GridColumn
:
parserOptions: {
caseSensitive: true,
allowedChars: [],
}
pass - import GridColumn from "components/GridColumn";
fail - import gridColumn from "components/GridColumn";
fail - import Gridcolumn from "components/GridColumn";
fail - import gridcolumn from "components/GridColumn";
fail - import Grid-Column from "components/GridColumn";
fail - import Grid_Column from "components/GridColumn";
fail - import GRIDCOLUMN from "components/GridColumn";
etc...
edit: typo
@Pearce-Ropion while the casing should ideally match, remember that not all filesystems are case-sensitive.
@Pearce-Ropion while the casing should ideally match, remember that not all filesystems are case-sensitive.
Of course, thats why I suggested it as an optional setting. My reasoning here that some people have the luxury of knowing what systems their code is being developed on (for example, every engineer at my company is required to use a linux machine). Also, after having a glance at the code, it looks like the isCompatible()
fn is doing a string equality check which would make it relatively easy to add these options.
Suggested changes snippet
/**
* @param {string} filename
* @param {object} options
* @returns {string}
*/
function normalizeFilename(filename, options) {
const allowedCharsRegex = new RegExp(`[${options.allowedChars.map(c => `\${c}`)}]`, 'g');
if (options.caseSensitive) {
return filename.replace(allowedCharsRegex, '');
}
return filename.replace(allowedCharsRegex, '').toLowerCase()
}
/**
* Test if local name matches filename.
* @param {string} localName
* @param {string} filename
* @param {object} options
* @returns {boolean}
*/
function isCompatible(localName, filename, options) {
const allowedCharsRegex = new RegExp(`[${options.allowedChars.map(c => `\${c}`)}]`, 'g');
let normalizedLocalName = localName.replace(allowedCharsRegex, '');
if (!options.caseSensitive) {
normalizedLocalName = normalizedLocalName.toLowerCase();
}
return (
normalizedLocalName === normalizeFilename(filename, options) ||
normalizedLocalName === normalizeFilename(removeExtension(filename), options)
)
}
It will be awesome to have this rule 👍 Let's merge this thing 🚀
https://github.com/benmosher/eslint-plugin-import/issues/325#issuecomment-280840161
I think that should be part of this. When would you ever want to enforce this for an import name and not the export name, granted it's an internal module.
Does this need further work or is it done?
It needs further work, as far as I'm aware. I'll mark it as a draft.
I'm also working on an NPM package. But is quite some work because you need lots of options for customization. Will write when it's published.
Is there any update on this? It would be great to have this as part of eslint-plugin-import
IMO