Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rules for directory names #23

Open
markalfred opened this issue Jun 23, 2017 · 10 comments
Open

Rules for directory names #23

markalfred opened this issue Jun 23, 2017 · 10 comments

Comments

@markalfred
Copy link

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

@AndersDJohnson
Copy link

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

@selaux
Copy link
Owner

selaux commented Aug 28, 2017

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

@vhlongon
Copy link

vhlongon commented Apr 5, 2018

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
Copy link

vhlongon commented Apr 5, 2018

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.

@selaux
Copy link
Owner

selaux commented Apr 6, 2018

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

@fsmaia
Copy link

fsmaia commented Mar 28, 2020

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

@Xooone47
Copy link

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?

@fsmaia
Copy link

fsmaia commented Apr 26, 2021

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

@YuriiBoikoOpn
Copy link

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

@Igorkowalski94
Copy link

Igorkowalski94 commented Oct 1, 2023

As an alternative, you can use eslint-plugin-project-structure

Cloud Shows an illustrated sun in light mode and a moon with stars in dark mode. Cloud

FolderOwl
eslint‑plugin-project‑structure

ESLint plugin with rules to help you achieve a scalable, consistent, and well-structured project.

Create your own framework! Define your folder structure, advanced naming conventions, file composition, and create independent modules.

Take your project to the next level and save time by automating the review of key principles of a healthy project!

npmnpm downloadsCheck, test, buildSponsorGitHub Repo stars

project‑structure/​folder‑structure

Enforce rules on folder structure to keep your project consistent, orderly and well thought out.

Rocket Features:

  • Validation of folder structure. Any files/folders outside the structure will be considered an error.
  • File/Folder name regex validation with features like wildcard * and treating . as a character, along with other conveniences.
  • Build in case validation.
  • Inheriting the folder's name. The file/folder inherits the name of the folder in which it is located. Option of adding your own prefixes/suffixes or changing the case.
  • Enforcing the existence of a files/folders when a specific file/folder exists. For example, if ./src/Component.tsx exists, then ./src/Component.test.tsx and ./src/stories/Component.stories.tsx must also exist.
  • Reusable rules for folder structures.
  • An option to create a separate configuration file with TypeScript support.
  • Forcing a nested/flat structure for a given folder.
  • Support for all file extensions.
  • Folder recursion. You can repeatedly nest a folder structure and set a limit on the nesting depth. There is also an option to change the rule at the final level, such as flattening the folder structure.
  • Fewer repetitions and precise error messages, even for deeply nested folders (recursion), by representing the folder structure as a tree.
  • Checking the length of paths and notifying when the limit is exceeded.

project‑structure/​independent‑modules

A key principle of a healthy project is to prevent the creation of a massive dependency tree, where removing or editing one feature triggers a chain reaction that impacts the entire project.

Create independent modules to keep your project scalable and easy to maintain. Get rid of dependencies between modules and create truly independent functionalities.

Rocket Features:

  • Creating independent modules in which you control what can be imported (e.g. types, functions, components of one functionality cannot be imported into another functionality).
  • The ability to create very detailed rules, even for nested folder structures. Whether it's a large module, a sub-module, or a single file, there are no limitations.
  • Disabling external imports (node_modules) for a given module (Option to add exceptions).
  • Non-relative/relative imports support.
  • Support for imports without extension.
  • Reusable import patterns.
  • Support for path aliases. The plugin will automatically detect your tsconfig.json and use your settings. There is also an option to enter them manually.
  • An option to create a separate configuration file with TypeScript support.

project‑structure/​file‑composition

Enforce advanced naming rules and prohibit the use of given selectors in a given file.

Have full control over what your file can contain and the naming conventions it must follow.

Rocket Features:

  • File composition validation.
  • Supported selectors: class, function, arrowFunction, type, interface, enum, variable, variableCallExpression, variableTaggedTemplateExpression.
  • Rules for exported selectors, selectors in the root of the file and nested/all selectors in the file. They can be used together in combination.
  • Prohibit the use of given selectors in a given file. For example, **/*.consts.ts files can only contain variables, **/*.types.ts files can only contain enums, interfaces and types.
  • Enforcing a maximum of one main function/class per file.
  • Inheriting the filename as the selector name. Option to add your own prefixes/suffixes, change the case, or remove parts of the filename.
  • Selector name regex validation.
  • Build in case validation.
  • Different rules for different files.
  • An option to create a separate configuration file with TypeScript support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants