eslint-plugin-filenames icon indicating copy to clipboard operation
eslint-plugin-filenames copied to clipboard

Rules for directory names

Open markalfred opened this issue 7 years ago • 10 comments

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... 💥

markalfred avatar Jun 23 '17 18:06 markalfred

@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 avatar Aug 27 '17 18:08 AndersDJohnson

@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 😉

selaux avatar Aug 28 '17 17:08 selaux

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

vhlongon avatar Apr 05 '18 08:04 vhlongon

How can I change which root folder is sent? It should differ to match-dirname tests, since I don't want /fooas in the other tests.

vhlongon avatar Apr 05 '18 12:04 vhlongon

Can you upload the code, so I can have a look at it? I don't fully understand the question yet...

selaux avatar Apr 06 '18 08:04 selaux

I would love to contribute to it too. I have developed a rule enforcing a custom file structure, but it could be easily adjusted.

fsmaia avatar Mar 28 '20 20:03 fsmaia

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?

Xooone47 avatar Apr 26 '21 09:04 Xooone47

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) },
          });
        }
      },
    };
  },
};

fsmaia avatar Apr 26 '21 17:04 fsmaia

also will be great to have similar rule for folders, as you have for files: filename-case

YuriiBoikoOpn avatar Jul 20 '22 13:07 YuriiBoikoOpn

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.

Igorkowalski94 avatar Oct 01 '23 08:10 Igorkowalski94