Skip to content

moso/eslint-config

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@moso/eslint-config

npm

Flat ESLint config for JavaScript, TypeScript, Vue, React, and more.

Legacy Version.

Features

  • ESLint Flat config with reasonable but opinionated defaults
  • Single quotes, semi enabled, sorted imports, dangling commas,
  • Aimed to be used without Prettier
  • Designed to work with JSX, TypeScript, Vue, and React out of the box
  • Stylistic rules implemented by default
  • Lints for json and yaml
  • Respects .gitignore by default
  • Requires ESLint v9.5.0+

Note

Since v1.0.0, this config is rewritten for the new ESLint Flat config format.

ESLint v9.5.0+ is now required.

Warning

While I'm very appreciative with every single install of this config, please keep in mind that this config is still a personal, opinionated config. How I like things set up might not fit everyone, or every usecase.

If you're using this config directly, I suggest you review the changes with every update. Or if you want more control over the very core of this config, feel free to fork it. Thanks!

Usage

Install

I like to use Bun because it's hella fast. Thus all the install instructions are with Bun. If you use something else, check the syntax with your favorite package manager.

bun add -dev eslint @moso/eslint-config

Create eslint.config.js in the root of your project:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso();
Combine with legacy config:

If you still use some configs from the legacy eslintrc format, you can use the @eslint/eslintrc package to convert them to the flat config.

// eslint.config.js
import moso from '@moso/eslint-config';
import { FlatCompat } from '@eslint/eslintrc';

const compat = new FlatCompat()

export default moso(
    {
        ignores: [],
    },

    // Legacy config
    ...compat.config({
        extends: [
            'eslint:recommended',
            // Other extends...
        ],
    })

    // Other flat configs...
);

Note that .eslintignore no longer works in Flat config, see customization for more details.

Add script for package.json

For example:

{
    "scripts": {
        "lint": "eslint",
        "lint:fix": "eslint --fix"
    }
}

VS Code support (auto fix)

Details

Install VS Code ESLint extension

Add the following settings to your .vscode/settings.json:

{
  // Disable the default formatter, use eslint instead
  "prettier.enable": false,
  "editor.formatOnSave": false,

  // Auto fix
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never"
  },

    // You can silent specific rules in you IDE, but still auto fix them
  "eslint.rules.customizations": [
    { "rule": "@stylistic/*", "severity": "off", "fixable": true },
    { "rule": "*-indent", "severity": "off", "fixable": true },
    { "rule": "*-spacing", "severity": "off", "fixable": true },
    { "rule": "*-spaces", "severity": "off", "fixable": true },
    { "rule": "*-order", "severity": "off", "fixable": true },
    { "rule": "*-dangle", "severity": "off", "fixable": true },
    { "rule": "*-newline", "severity": "off", "fixable": true },
    { "rule": "*quotes", "severity": "off", "fixable": true },
    { "rule": "*semi", "severity": "off", "fixable": true }
  ],

  // Enable eslint for all supported languages
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
    "json",
    "jsonc",
    "yaml"
  ]
}

Customization

Since v1.0, this config has been migrated to ESLint Flat config. It provides much better organization and composition. And speed!

Normally you only need to import the moso preset:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso();

If you want more control, you can configure each intetegration, like so:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    // Disable stylistic formatting rules
    stylistic: false,

    // Or customize the stylistic rules
    stylistic: {
        indent: 2, // 4, or 'tab'
        quotes: 'single', // or 'double'
    },

    // TypeScript, Vue, and React are auto-detected, you can also explicitly enable them:
    typescript: true,
    react: true,
    vue: true,

    // Disable jsonc and yaml support
    jsonc: false,
    yaml: false,

    // `.eslintignore` is no longer supported in Flat config, use `ignores` instead
    ignores: [
        '**/dist',
        // ...globs
    ],
});

Rules overrides

The moso configurator function accepts any number of custom config overrides. And certain rules will only be enabled for specific file types. Example, vue/* rules are only applied on .vue-files. If you want to override the rules, you need to specify the file extension:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso(
    {
        // First argument are configurations for moso's config
        vue: true,
        typescript: true,
    },
    {
        // Second argument and beyond are ESLint Flat Configs
        // You can have as many as you want here.

        // Example of overriding vue/* rules on `.vue`-files using the Vue file glob:
        files: ['**/*.vue'],
        rules: {
            'vue/multi-word-component-names': ['error', { ignores: [] }],
        },
    },
    {
        rules: {},
    },
);

Since v1.0.0, the configurator function returns a FlatConfigComposer-object from antfu's eslint-flat-config-utils, which gives you even more flexibility when composing the config, as you can dot your way through:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso()
    .prepend(
        // Configs before the main config
    )
    .override(
        // Override any named config
        'moso/javascript/rules',
        {
            rules: {
                'no-var': 'off',
            },
        },
    )
    // You can also remove rules entirely
    .removeRules(
        // ...
    );
Advanced example

You can import fine-grained configs and compose them as you want. Don't do this unless you know exactly what you're doing.

import {
    combine,
    comments,
    ignores,
    imports,
    javascript,
    jsdoc,
    jsonc,
    node,
    sortPackageJson,
    sortTsconfig,
    stylistic,
    typescript,
    unicorn,
    vue,
    yaml,
} from '@moso/eslint-config';

export default combine(
    ignores(),
    javascript(/* options */),
    comments(),
    node(),
    jsdoc(),
    imports(),
    unicorn(),
    typescript(/* options */),
    stylistic(),
    vue(/* options */),
    jsonc(),
    yaml(),
);

Optional configs

There are multiple configs that are deemed "optional". Most of them are set to true (enabled), some are auto-detect. An example of auto-detection, TypeScript, Vue, and React are set to auto-detect, as there are checks in those configs and enable them if their packages are present. But should you want to enable/disable these explicitly, or if my check doesn't auto-detect it, this is how it's done:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    // Enable TypeScript
    typescript: true,

    // Enable Vue
    vue: true,

    // Enable React
    react: true,
});

Note: Since Vue 2 has reached EOL, this config does not support Vue 2. If you need to support for Vue 2, you'll need to disable the imported configs from Vue 3, and replace them with the Vue 2 ones. You can see an inspiring example on eslint-plugin-vue. I recommend upgrading to Vue 3 if possible.

Optional rules

This config also provides some optional plugins/rules for extended usage.

Perfectionist

The plugin eslint-plugin-perfectionist allows you to sort object keys, imports, types, enums and JSX props with auto fix. I love it, and encourage everyone to use it. It gives you a lot more consistency across projects and developers. The plugin is installed and enabled by default, but only rules for sorting imports are activated.

If you wish to override or extend it, you can by overriding the perfectionist integration, or adding to your own rules.

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso(
    {
        // Overriding the sort-imports
        perfectionist: {
            overrides: {
                'perfectionist/sort-imports': 'off',
            },
        },
    },
    {
        // Or adding your own rules
        rules: {
            'perfectionist/sort-enums': ['error', { type: 'natural', order: 'asc', locales: 'da-DK' }],
        },
    },
);

However, you can also opt-in to a rule in each file individually using configuration comments.

/* eslint perfectionist/sort-objects: 'error' */
const objectWantedToSort = {
    a: 2,
    b: 1,
    c: 3,
};

Note: If you want to disable it, you can do it in two ways.

Individually

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    // Disable Perfectionist
    perfectionist: false,
});

Part of lessOpinionated

There's an option to actually make this config "less opinionated". This will also strip most of the @stylistic rules, but more about that at the Less Opnionated-section.

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    // Less opnionated
    lessOpnionated: true,
});

Type-aware rules

You can also optionally enable the type-aware rules by passing the path of your tsconfig.json to the typescript config.

This enables for much deeper insight into your code.

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    typescript: {
        tsconfigPath: 'tsconfig.json',
    },
});

Editor specific non-fixes

Some rules are deemed as 'non-fixable' when inside your editor with ESLint integration:

This is to prevent unused imports from getting removed by your editor when refactoring to get a better developer experience. However, the rules will still be applied when you run ESLint from your terminal. You can disable this behavior like so:

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    isInEditor: false,
});

Lint Staged

Linting and auto-fixing before every commit is easy, you just add the following to your package.json:

{
    "simple-git-hooks": {
        "pre-commit": "bunx lint-staged"
    },
    "lint-staged": {
        "*": "eslint --fix"
    }
}

and then

bun add -dev lint-staged simple-git-hooks

# to activate the hooks
bunx simple-git-hooks

View which rules are enabled

Antfu built a visual tool that can help you view what rules are enabled in your project: @eslint/config-inspector.

To view it in action, navigate to the root of your project that contains your eslint.config.js and run:

bunx @eslint/config-inspector

FAQ

I want it less opnionated

No problem. I've extracted the things that I've deemed very opinionated in each integration, and made a setting that helps you disable all of it in one go.

// eslint.config.js
import moso from '@moso/eslint-config';

export default moso({
    lessOpinionated: true,
});

Prettier? dprint?

You can still use these to format files that aren't linted with this config, however, I strongly recommend you only format your code with ESLint, as Pretter and other AST-reading-then-reprint projects tend to ignore stuff like the original line breaks and might also cause inconsistent diffs when commiting code.

How to format CSS?

You will need to install and configure stylelint yourself, unfortunately.

I prefer this or that rule

Fine, you can always override the rules locally in your project to fit your needs. If that doesn't cut it, you're welcome to fork this project and maintain your own config.

Inspiration

This eslint-config takes inspiration from (and uses some of) @antfu/eslint-config and @rubiin/eslint-config respectively. Thank you to everyone who contributed to these configs.

Most of the rules are the same, however, there are some differences:

  • Opinionated rules
  • Enables Stylistic per default
  • React detection, no need to enable it
  • Includes dependencies rather than asking you to install them
  • Deprecated Vue 2 support
  • Simplification in some areas
  • Less clutter, shipping with less "smart" features
  • No dangerous plugin renaming, except for eslint-plugin-n which is renamed to node for readability

License

MIT License

About

Opinionated eslint configs

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published