Skip to content

ESLint

The ESLint config file for this repository is fairly complex. The different configuration objects target different groups of files to apply different rules. You can refer to this page for more information on how ESLint processes these configuration objects.

Generally, there are two types of linting rules:

  1. Repository only code (used for development of modules)
  2. Module code (Code that is actually intended to be used in Source)

Linting rules for module code tend to be stricter as there are conventions that need to be followed to ensure that users of Source have a more unified experience. There are also many features supported by Javascript/Typescript that aren't supported in Source.

ESLint does provide a configuration inspector which can be started using . It provides more information on what rules are applied to which files and also other information like what rules are considered deprecated.

Configuration Conventions

Our linting configurations often inherit from recommended configurations provided by plugins. However, not all of the rules that are configured by these configurations make sense for the repository at large. This requires that we manually override some of the settings provided by these configurations.

When changing a rule's configuration, leave a comment explaining what the original configuration for that rule was:

js
{
  name: 'Markdown Files',
  extends: [markdown.configs.recommended],
  files: ['**/*.md'],
  ignores: [
    // These are generated via Typedoc, we don't have to lint them
    'docs/src/lib/modules-lib/**/*.md',
  ],
  processor: mdx.createRemarkProcessor({
    lintCodeBlocks: true,
    ignoreRemarkConfig: true
  }),
  language: 'markdown/gfm',
  languageOptions: {
    frontmatter: 'yaml'
  },
  plugins: { markdown },
  rules: {
    'markdown/no-missing-label-refs': 'off', // was error
    'markdown/no-multiple-h1': 'off',        // was error
    'markdown/require-alt-text': 'off',      // was error
  }
},

Where possible, also provide an explanation for why that rule has been configured as such:

js
{
  extends: tseslint.configs.recommended,
  name: 'Global Typescript Rules',
  files: ['**/*.{ts,cts,tsx}'],
  // Markdown virtual files need to be ignored because the type-aware rules
  // don't work with them
  ignores: ['**/*.md/**/*.{ts,tsx}'],
  languageOptions: {
    parser: tseslint.parser,
    parserOptions: {
      // Prevent the parser from going any higher in the directory tree
      // to find a tsconfig
      tsconfigRootDir: import.meta.dirname,
      project: true
    }
  },
  plugins: {
    '@typescript-eslint': tseslint.plugin,
  },
  rules: {
    'no-unused-vars': 'off', // Use the typescript eslint rule instead

    'jsdoc/no-types': 'warn',

    '@stylistic/type-annotation-spacing': ['warn', { overrides: { colon: { before: false, after: true } } }],

    '@typescript-eslint/ban-ts-comment': 'error',
    '@typescript-eslint/consistent-type-assertions': ['warn', { assertionStyle: 'as' }],
    '@typescript-eslint/no-duplicate-type-constituents': 'off', // Was 'error'
    '@typescript-eslint/no-explicit-any': 'off', // Was 'error'
    '@typescript-eslint/no-import-type-side-effects': 'error',
    '@typescript-eslint/no-redundant-type-constituents': 'off', // Was 'error'
    // This rule doesn't seem to fail locally but fails on the CI
    // '@typescript-eslint/no-unnecessary-type-assertion': 'error',
    '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // Was 'error'
    '@typescript-eslint/only-throw-error': 'error'
  }
},

Linting Markdown Code Examples

Markdown gives us the ability to embed code blocks within regular text. ESLint is able to lint this code with the functionality provided by the eslint-plugin-mdx package, which provides a processor that makes these code blocks available to ESLint.

Because typescript-eslint requires a tsconfig to be able to lint any kind of Typescript code, it can't actually be used with any type-aware rules. Furthermore, code examples are usually incomplete snippets of Typescript/Javascript, so a lot of the typical rules in use don't really apply to these. Thus, code examples have their own separate configurations.

Linting JSON Files

For the most part, there are only stylistic rules that need to be applied to JSON files. This is why this repository doesn't use the official @eslint/json package for linting JSON files. Instead. the parser from eslint-plugin-json is used so that stylistic rules can be applied to the JSON files. This does mean that none of the rules from @eslint/json can be applied directly.

Collecting Linting Stats

The lint commands can be run with the --stats option, which causes ESLint to collect the time taken by each rule to lint a given file. The outputs are written to the build directory as CSV files.