eslint-plugin-filenames
eslint-plugin-filenames copied to clipboard
Rules for directory names
This is a feature I would personally use, but not sure if there's any demand for it from other folks or if it's better off as its own plugin.
For instance, I want all files and directories to be kebab-cased so that there are no issues between case-insensitive (OSX dev environments) and case-sensitive (Linux deployment environments). Currently, though, with this configuration:
"filenames/match-regex": [2, "^(-|[a-z])+$"],
I could create this file with no problem:
app/Components/Auth/auth-header.jsx
On my OSX machine, I could import AuthHeader from 'app/components/auth/auth-header'
with no problem.
But as soon as I deploy to a linux environment... 💥
@selaux @markalfred I would love this feature as well. For backwards compatibility, maybe enable as an option to filenames/match-regex
to match full file paths instead of just base file names?
Not sure if we should try to trim the absolute paths to be relative to the project root - may be tricky.
Would you accept a pull request and consider a release, or is it not worth my time?
@AndersDJohnson Sure, I would gladly accept a PR. match-regex
could be extended to match each path segment relative to root. Not sure how to find the root though 😉
Hi @selaux I am working on this but I am not sure how to set the root folder in my tests. I have a failing test now that should pass:
{
code: testCode,
filename: "SomeDir/VariableName.js",
// parserOptions: { ecmaVersion: 6, sourceType: "module" },
options: ['pascal']
},
The Dirname returned is foo/SomeDir
where it should be Foo/SomeDir
, but I am not sure how to set foo
to Foo
How can I change which root folder is sent? It should differ to match-dirname
tests, since I don't want /foo
as in the other tests.
Can you upload the code, so I can have a look at it? I don't fully understand the question yet...
I would love to contribute to it too. I have developed a rule enforcing a custom file structure, but it could be easily adjusted.
I would love to contribute to it too. I have developed a rule enforcing a custom file structure, but it could be easily adjusted.
what about your rules now?
As it is small, I will post its entire code here.
Keep in mind that is was developed for an opinionated file structure (feature-based with layers inside of the features).
module.exports = {
meta: {
docs: {
description: 'This rule enforces a file path to match the guideline',
recommended: true,
},
messages: {
[MATCH_PATH_MESSAGE]: "File path '{{ pathDir }}' should match the guideline",
},
},
create: (context) => {
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
const joinOptions = (options) => `(${options.join('|')})`;
return {
Program: (node) => {
const filename = path.resolve(context.getFilename()).replace(/\\/g, '/');
const rootFile = joinOptions(['serviceWorker', 'store']);
const validFiles = [
`${SRC_FOLDER}/${rootFile}.(js|ts)`, // src root files
`${SRC_FOLDER}/index((.integration)?.test)?.(js|ts|tsx)`, // src root file
`${SRC_FOLDER}/router.(js|tsx)`, // root router file
`${SRC_FOLDER}/modules/index.(js|ts)`, // modules entrypoint
`${SRC_FOLDER}/${I18N_LAYER_FOLDER}/${I18N_CASE}.json`,
`${FEATURE_FOLDER}(/${LAYER_FOLDER})?/index((.integration)?.test)?.(js|ts)`, // entrypoints
`${FEATURE_FOLDER}/${NAMESPACED_LAYER_FOLDER}(/${KEBAB_CASE})?/index(.test)?.(js|ts)`,
`${FEATURE_FOLDER}/${LAYERS.DECORATORS}(/${KEBAB_CASE})?/index(.test)?.tsx`, // decorators may have JSX
`${FEATURE_FOLDER}/${CONSTANTS_LAYER_FOLDER}/${KEBAB_CASE}.(js|ts)`,
`${FEATURE_FOLDER}/${REACT_LAYER_FOLDER}(/${PASCAL_CASE})?/index.scss`,
`${FEATURE_FOLDER}/${REACT_LAYER_FOLDER}(/${PASCAL_CASE})?/index((.integration)?.test|.story)?.(js|tsx)`,
`${FEATURE_FOLDER}/${TYPESCRIPT_LAYER_FOLDER}/${PASCAL_CASE}.ts`,
`${FEATURE_FOLDER}/${FREESTYLE_LAYER_FOLDER}.*`,
];
const validFilesRegExp = new RegExp(`${joinOptions(validFiles)}$`);
const fileIndex = filename.indexOf('src');
if (filename.match('src') && !filename.match(validFilesRegExp)) {
context.report({
node,
messageId: MATCH_PATH_MESSAGE,
data: { pathDir: filename.slice(fileIndex) },
});
}
},
};
},
};
also will be great to have similar rule for folders, as you have for files: filename-case
As an alternative, you can use eslint-plugin-project-structure
features: ✅ Validation of project structure (Any files/folders outside the structure will be considered an error). ✅ Validation of folder and file names. ✅ Name case validation. ✅ Name regex validation. ✅ File extension validation (Support for all extensions). ✅ Inheriting the parent's name (The child inherits the name of the folder in which it is located). ✅ Folder recursion (You can nest a given folder structure recursively). ✅ Forcing a nested/flat structure for a given folder.