npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

linter-bundle

v6.3.0

Published

Ready-to use bundle of linting tools, containing configurations for ESLint, stylelint and markdownlint.

Downloads

1,147

Readme

linter-bundle

npm version Dependency Status Known Vulnerabilities npm MIT license

Ready-to use bundle of linting tools, containing configurations for

The linting tools are running in parallel, which can improve the performance by more than 20 percent.

Used plugins

This setup is using the following additional plugins:

ESLint

Beside that, the following additional rules are part of this bundle:

stylelint

Beside that 73 stylistic rules has been forked from [email protected], which have been removed in [email protected], are part of this bundle.

Previously used, but now unmaintained plugins

Unfortunately a couple of previously used plugins are not regularly maintained or depend on unmaintained third-party code which blocks them from updating, so they don't provide updates for the major releases of the linters (ESLint and Stylelint). For that reason the following plugins are not used anymore:

If these plugins are maintained again, the plugins will also be used again.

Install

Ensure you are using atleast Node.js version 18.2.0.

npm install linter-bundle --save-dev

Usage examples

package.json

{
  "scripts": {
    "lint": "lint tsc ts sass md audit",
    "lint-different-configurations": "lint tsc --tsconfig=./path1/tsconfig.json tsc --tsconfig=./path2/tsconfig.json ts sass md audit"
  }
}

.eslintrc.js

module.exports = {
  extends: [
    require.resolve('linter-bundle/eslint.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-gatsby.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-javascript.cjs'),
    require.resolve('linter-bundle/eslint/overrides-javascript-lazy.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-jest.cjs'),
    require.resolve('linter-bundle/eslint/overrides-jsdoc.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-react.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-storybook.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-type-declarations.cjs'),
    // require.resolve('linter-bundle/eslint/overrides-worker.cjs')
  ]
};
Available extends

Source | Description | Rules setup -|-|- linter-bundle/eslint.cjs | General rule setup. This is also the base for the following overrides. | View linter-bundle/eslint/overrides-gatsby.cjs | Settings for Gatsby-based projects. | View linter-bundle/eslint/overrides-javascript.cjs | Strict settings for JavaScript files, which enforces correct types everywhere. | View linter-bundle/eslint/overrides-javascript-lazy.cjs | Can be used instead of overrides-javascript. It's less strict and allows the any type. | View linter-bundle/eslint/overrides-jest.cjs | Settings for projects using Jest. | View linter-bundle/eslint/overrides-jsdoc.cjs | Settings for projects using JSDoc comments. | View linter-bundle/eslint/overrides-react.cjs | Settings for projects using React comments. | View linter-bundle/eslint/overrides-storybook.cjs | Settings for projects using Storybook comments. | View linter-bundle/eslint/overrides-type-declarations.cjs | Settings for type declaration files (.d.ts). | View linter-bundle/eslint/overrides-worker.cjs | Settings for projects using Web Workers. | View

stylelint.config.js

module.exports = {
  extends: 'linter-bundle/stylelint.cjs'
};

.markdownlint.json

{
  "extends": "node_modules/linter-bundle/markdownlint/base.json"
}

.gitignore / .npmignore

.eslintcache

.linter-bundle.json / .linter-bundle.cjs / .linter-bundle.js

linter-bundle supports a couple of additional options, which can be configured in the configuration file, in the root of your project.
Some of the options are also available as command line arguments (see below).
The file itself, and any of the options is optional.

Minimum example configuration (.linter-bundle.json)

{
  "verbose": true,
  "timing": true,
  "git": true,
  "tsc": {
    "tsconfig": "./tsconfig.lint.json"
  },
  "ts": {
    "tsconfig": "./tsconfig.lint.json",
    "include": ["./included/*.ts"],
    "exclude": ["./excluded/*.ts"],
    "overrides": {
      "general": {
        "no-restricted-globals": {
          "additionalRestrictions": [
            {
              "name": "fetch",
              "message": "Use Utils.fetchWithTimeout() instead."
            }
          ]
        },
        "no-restricted-properties": {
          "additionalRestrictions": [
            {
              "object": "localStorage",
              "property": "getItem",
              "message": "Use StorageHelper.getItem() instead."
            }
          ]
        },
        "no-restricted-syntax": {
          "additionalRestrictions": [
            {
              "selector": "NewExpression[callee.name=\"Blob\"]",
              "message": "Use BlobHelper.create() instead of new Blob()."
            }
          ]
        },
        "import/order": {
          "additionalExternalPatterns": ["@sentry/*"]
        },
        "@typescript-eslint/naming-convention": {
          "additionalOptions": [
            {
              "selector": "variable",
              "modifiers": ["const"],
              "format": ["camelCase"]
            }
          ]
        }
      },
      "react": {
        "react/forbid-component-props": {
          "allowClassNameFor": ["Checkbox", "Grid", "GridItem", "Button"],
          "allowStyleFor": ["Grid", "GridItem"]
        }
      }
    }
  },
  "sass": {
    "include": ["./included/*.ts"],
    "patternPrefix": "--my-prefix"
  },
  "md": {
    "include": ["./included/*.md"],
  },
  "audit": {
    "minSeverity": "high",
    "exclude": ["975", "1751"]
  },
  "files": {
    "restrictions": [
      {
        "basePath": "./src",
        "allow": [
          "components/**/index.tsx",
          "utils/{index.ts,lib/[a-z]+([a-zA-Z])?(.spec).ts}"
        ],
        "disallow": [
          "components/NotAllowed/index.tsx"
        ]
      }
    ]
  }
}

Maximum example configuration (.linter-bundle.js)

module.exports = {
  /**
   * Same as `--verbose` command line argument.
   * 
   * @type {boolean}
   */
  verbose: true,

  /**
   * Same as `--timing` command line argument.
   * 
   * @type {boolean}
   */
  timing: true,

  /**
   * Same as `--git` command line argument.
   * 
   * @type {boolean}
   */
  git: true,

  /**
   * Configuration, specific to the `tsc` command.
   */
  tsc: {
    /**
     * `verbose`, `timing` and `git` are the same as in the root node.
     */
    verbose: true,
    timing: true,
    git: true,

    /**
     * Same as `--tsconfig` command line argument.
     * 
     * @type {string}
     */
    tsconfig: './tsconfig.lint.json'
  },

  /**
   * Configuration, specific to the `ts` command.
   */
  ts: {
    /**
     * `verbose`, `timing` and `git` are the same as in the root node.
     */
    verbose: true,
    timing: true,
    git: true,

    /**
     * Same as `--tsconfig` command line argument.
     * 
     * @type {string}
     */
    tsconfig: './tsconfig.lint.json',

    /**
     * Same as `--include` command line argument.
     * 
     * @type {string[]}
     */
    include: ['./included/*.ts'],

    /**
     * Same as `--exclude` command line argument.
     * 
     * @type {string[]}
     */
    exclude: ['./excluded/*.ts'],

    /**
     * Overrides and extensions for specific ESLint rules.
     */
    overrides: {
      /**
       * Rules that are applied to `linter-bundle/eslint.cjs`.
       */
      general: {
        'no-restricted-globals': {
          /**
           * Extend the `restrictions` of the `no-restricted-globals` rule.
           * 
           * @type {{ name: string; message: string; }[]}
           */
          additionalRestrictions: [
            {
              name: 'fetch',
              message: 'Use Utils.fetchWithTimeout() instead.'
            }
          ]
        },
        'no-restricted-properties': {
          /**
           * Extend the `restrictions` of the `no-restricted-properties` rule.
           * 
           * @type {{ object: string; property: string; message: string; }[]}
           */
          additionalRestrictions: [
            {
              object: 'localStorage',
              property: 'getItem',
              message: 'Use StorageHelper.getItem() instead.'
            }
          ]
        },
        'no-restricted-syntax': {
          /**
           * Extend the `restrictions` of the `no-restricted-syntax` rule.
           * 
           * @type {{ selector: string; message: string; }[]}
           */
          additionalRestrictions: [
            {
              selector: 'NewExpression[callee.name="Blob"]',
              message: 'Use BlobHelper.create() instead of new Blob().'
            }
          ]
        },
        'import/order': {
          /**
           * Extend the `externalPatterns` of the `import/order` rule.
           *
           * @type {string[]}
           */
          additionalExternalPatterns: ['@sentry/*']
        }
      },

      /**
       * Rules that are applied to `linter-bundle/eslint/overrides-react.cjs`.
       */
      react: {
        'react/forbid-component-props': {
          /**
           * Allows the `className` property for the specified components.
           *
           * @type {string[]}
           */
          allowClassNameFor: ['Checkbox', 'Grid', 'GridItem', 'Button'],

          /**
           * Allows the `style` property for the specified components.
           *
           * @type {string[]}
           */
          allowStyleFor: ['Grid', 'GridItem']
        }
      }
    }
  },

  /**
   * Configuration, specific to the `sass` command.
   */
  sass: {
    /**
     * `verbose`, `timing` and `git` are the same as in the root node.
     */
    verbose: true,
    timing: true,
    git: true,

    /**
     * Same as `--include` command line argument.
     * 
     * @type {string[]}
     */
    include: ['./included/*.ts'],

    /**
     * The prefix used for the 'custom-media-pattern' (`@media (--my-prefix-foo)`) and 'custom-property-pattern' (`var(--my-prefix-bar)`) rule.
     *
     * If not defined, these rules are disabled.
     */
    patternPrefix: '--my-prefix'
  },

  /**
   * Configuration, specific to the `audit` command.
   */
  md: {
    /**
     * Same as `--include` command line argument.
     * 
     * @type {string[]}
     */
    include: ['./included/*.ts']
  },

  /**
   * Configuration, specific to the `audit` command.
   */
  audit: {
    /**
     * `verbose`, `timing` and `git` are the same as in the root node.
     */
    verbose: true,
    timing: true,
    git: true,

    /**
     * Same as `--min-severity` command line argument.
     * 
     * @type {'info' | 'low' | 'moderate' | 'high' | 'critical'}
     */
    minSeverity: 'high',

    /**
     * Same as `--exclude` command line argument.
     * 
     * @type {string[]}
     */
    exclude: ['975', '1751']
  },

  /**
   * Configuration, specific to the `files` command.
   */
  files: {
    /**
     * `verbose`, `timing` and `git` are the same as in the root node.
     */
    verbose: true,
    timing: true,
    git: true,

    /**
     * Array of restrictions for different base paths.
     *
     * The configuration is equal to the `restricted-filenames` ESLint plugin.
     * This plugin is using the configuration here, if ESLint is used outside of `linter-bundle` (e.g. in VSCode).
     *
     * @see https://github.com/jens-duttke/linter-bundle/blob/main/eslint/rules/restricted-filenames.md
     */
    restrictions: [
      {
        /**
         * Same as `--exclude` command line argument.
         * 
         * @type {string}
         */
        basePath: './src',

        /**
         * Glob pattern Same as `--exclude` command line argument.
         * 
         * @type {string[]}
         */
        allow: [
          'components/**/index.tsx',
          'utils/{index.ts,lib/[a-z]+([a-zA-Z])?(.spec).ts}'
        ],

        /**
         * Same as `--exclude` command line argument.
         * 
         * @type {string[]}
         * 
         */
        disallow: [
          'components/NotAllowed/index.tsx'
        ]
      }
    ]
  }
}

Available commands

The command line arguments are separated in groups. Here are some examples:

# Run File restrictions, TypeScript compiler, ESLint, Stylelint, Markdownlint, and audit in the given order, using the default configuration
lint files tsc ts sass md audit

# Run ESLint and Audit, and show their terminal output even on success
lint --verbose ts audit

# Run ESLint and Audit, and show the ESLint terminal output even on success
lint ts --verbose audit

# Run TypeScript compiler and ESLint, but with different tsconfig.json files
lint tsc --tsconfig=./cypress/tsconfig.json ts --tsconfig=./.storybook/tsconfig.json

# Run TypeScript compiler twice with different configurations
lint tsc tsc --tsconfig="./cypress/tsconfig.json"

Below, you can find the available command line arguments and what they are doing.

General optional command line arguments

Argument | Description | Example -|-|- --verbose | By default, the terminal output of linters is only shown if an error occurs. Use this option to show their terminal output even on success. | --verbose --timing | Show information how long each linting process was running. | --timing --git | Experimental Only lint (ESLint, Stylelint and Markdownlint) files which have been detected as changed (compared to the upstream branch) by Git. This can result into massive performance improvements on large code bases, but also lead to undetected issues with cross-file rules. | --git

lint files

Will check if the files in the project match the restrictions defined in the linter-bundle configuration file.

lint tsc

Will execute:

tsc --skipLibCheck --noEmit

Optional command line arguments for lint tsc

Argument | Description | Example -|-|- --tsconfig | Allows to specifiy a different tsconfig.json file. | --tsconfig=./cypress/tsconfig.json

lint ts

Will execute:

eslint "./**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}" --format unix

Additionally, the environment variable TIMING is set to 10, to show timing information about the 10 slowest rules.

Optional command line arguments for lint ts

Argument | Description | Example -|-|- --tsconfig | Allows to specifiy a different tsconfig.json file. | --tsconfig=./cypress/tsconfig.json --include | Patterns with files which should be considered | --include="./cypress/**/*.ts" --exclude | Patterns with files which should not be considered. Can be used multiple times for different patterns. Used as --ignore-pattern argument for ESLint. | --exclude="cypress" --exclude=".storybook"

lint sass

Will execute:

stylelint "src/**/*.scss" --formatter unix --report-needless-disables --report-invalid-scope-disables --report-descriptionless-disables

lint md

Will execute:

markdownlint **/*.md --ignore node_modules

lint audit

If a package.json exist, it will execute:

better-npm-audit audit -l moderate -p

If a yarn.lock exist, it will execute:

improved-yarn-audit --min-severity moderate --fail-on-missing-exclusions --ignore-dev-deps

Optional command line arguments for lint audit

Argument | Description | Example -|-|- --min-severity | Minimum severity to treat as an error, default is moderate (info, low, moderate, high, critical). Used as -l argument for better-npm-audit, and --min-severity argument for improved-yarn-audit. | --min-severity=moderate --exclude | Comma-separated list of advisory IDs to ignore. Used as -i argument for better-npm-audit, and --exclude argument for improved-yarn-audit. | --exclude=118,577

VSCode setup

ESLint

For VSCode I recommend the ESLint extension.

To ensure the ESLint plugins are correctly loaded, you need to adjust the settings of this plugin.

This can be done by adding these options to your .vscode/settings.json:

{
  "eslint.nodePath": "./node_modules/linter-bundle/node_modules/eslint",
  "eslint.options": {
    "overrideConfigFile": "./.eslintrc.js", // or "./.eslintrc.cjs" or "./eslintrc.json"
    "resolvePluginsRelativeTo": "./node_modules/linter-bundle",
    "rulePaths": ["./node_modules/linter-bundle/eslint/rules"],
    "reportUnusedDisableDirectives": "error",
  }
}

If the ESLint extension shows the following message on the bottom-right:

https://cdn.jsdelivr.net/gh/jens-duttke/linter-bundle@f7d514f/vscode-eslint-1.png

Click on "Select Node Path". A selection popup will appear at the top of the editor:

https://cdn.jsdelivr.net/gh/jens-duttke/linter-bundle@f7d514f/vscode-eslint-2.png

Here, choose the option "Use NODE_PATH value defined via setting".

stylelint

For VSCode I recommend the stylelint extension.

To ensure the stylelint plugins are correctly loaded, you need to adjust the settings of this plugin in your .vscode/settings.json:

{
  "stylelint.enable": true,
  "stylelint.validate": [
    "scss"
  ],
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false
}

Auto-fix code on save

In order to fix the code according to the ESLint/stylelint rules when saving, the following settings can be added to your .vscode/settings.json:

{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  }
}

Rulers

To visualize the max line-length rules in VSCode, you can activate rulers, by adding the following settings to your .vscode/settings.json:

{
  "[javascript]": {
    "editor.rulers": [300]
  },
  "[markdown]": {
    "editor.rulers": [300]
  },
  "[scss]": {
    "editor.rulers": [160]
  },
  "[typescript]": {
    "editor.rulers": [300]
  },
  "[typescriptreact]": {
    "editor.rulers": [300]
  }
}

FAQ

How to solve the problem Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser. ?

If you get such an error message:

Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: [any-name].js.
The file must be included in at least one of the projects provided.

the problem is most likely, that your tsconfig.json does not cover your JavaScript files and that you don't have a jsconfig.json file in your root directory. This is required by the @typescript-eslint to use TypeScript for linting of JavaScript files.

To solve this problem, either "include" your JavaScript files in your tsconfig.json (don't forget to set the compiler option "checkJs" to true) or create a jsconfig.json file in your root directory (this can be a copy of your tsconfig.json with an "include" of your JavaScript files).

In VSCode, in every file, the first line shows the error Definition for rule "no-unnecessary-typeof" was not found. eslint(no-unnecessary-typeof)

Please ensure that you've added the configuration options as described above ("VSCode setup" > "ESLint").