Skip to content

Commit

Permalink
Transition to eslint-config-airbnb-with-typescript
Browse files Browse the repository at this point in the history
- Migrate to newer `eslint-config-airbnb-with-typescript` from
  `eslint-config-airbnb`.
- Add also `rushstack/eslint-patch` as per instructed by
  `eslint-config-airbnb-with-typescript` docs.
- Update codebase to align with new linting standards.
- Add script to configure VS Code for effective linting for project
  developers, move it to `scripts` directory along with clean npm
  install script for better organization.
  • Loading branch information
undergroundwires committed Aug 4, 2023
1 parent 4d0ce12 commit ff84f56
Show file tree
Hide file tree
Showing 39 changed files with 2,391 additions and 693 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[*.{js,jsx,ts,tsx,vue}]
[*.{js,jsx,ts,tsx,vue,sh}]
indent_style = space
indent_size = 2
end_of_line = lf
Expand Down
181 changes: 3 additions & 178 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
const { rules: baseBestPracticesRules } = require('eslint-config-airbnb-base/rules/best-practices');
const { rules: baseErrorsRules } = require('eslint-config-airbnb-base/rules/errors');
const { rules: baseES6Rules } = require('eslint-config-airbnb-base/rules/es6');
const { rules: baseImportsRules } = require('eslint-config-airbnb-base/rules/imports');
const { rules: baseStyleRules } = require('eslint-config-airbnb-base/rules/style');
const { rules: baseVariablesRules } = require('eslint-config-airbnb-base/rules/variables');
const tsconfigJson = require('./tsconfig.json');
require('@rushstack/eslint-patch/modern-module-resolution');

module.exports = {
root: true,
Expand All @@ -17,9 +13,7 @@ module.exports = {
'plugin:vue/essential',

// Extends eslint-config-airbnb
// Added by Vue CLI
// Here until https://github.com/vuejs/eslint-config-airbnb/issues/23 is done
'@vue/airbnb',
'@vue/eslint-config-airbnb-with-typescript',

// Extends @typescript-eslint/recommended
// Uses the recommended rules from the @typescript-eslint/eslint-plugin
Expand Down Expand Up @@ -52,18 +46,6 @@ module.exports = {
mocha: true,
},
},
{
files: ['**/*.ts?(x)', '**/*.d.ts'],
parserOptions: {
// Setting project is required for some rules such as @typescript-eslint/dot-notation,
// @typescript-eslint/return-await and @typescript-eslint/no-throw-literal.
// If this property is missing they fail due to missing parser.
project: ['./tsconfig.json'],
},
rules: {
...getTypeScriptOverrides(),
},
},
{
files: ['**/tests/**/*.{j,t}s?(x)'],
rules: {
Expand Down Expand Up @@ -115,6 +97,7 @@ function getOpinionatedRuleOverrides() {
return {
// https://erkinekici.com/articles/linting-trap#no-use-before-define
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
// https://erkinekici.com/articles/linting-trap#arrow-body-style
'arrow-body-style': 'off',
// https://erkinekici.com/articles/linting-trap#no-plusplus
Expand All @@ -134,164 +117,6 @@ function getOpinionatedRuleOverrides() {
};
}

function getTypeScriptOverrides() {
/*
Here until Vue supports AirBnb Typescript overrides (vuejs/eslint-config-airbnb#23).
Based on `eslint-config-airbnb-typescript`.
Source: https://github.com/iamturns/eslint-config-airbnb-typescript/blob/v16.1.0/lib/shared.js
It cannot be used directly due to compilation errors.
*/
return {
'brace-style': 'off',
'@typescript-eslint/brace-style': baseStyleRules['brace-style'],

camelcase: 'off',
'@typescript-eslint/naming-convention': [
'error',
{ selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
{ selector: 'function', format: ['camelCase', 'PascalCase'] },
{ selector: 'typeLike', format: ['PascalCase'] },
],

'comma-dangle': 'off',
'@typescript-eslint/comma-dangle': [
baseStyleRules['comma-dangle'][0],
{
...baseStyleRules['comma-dangle'][1],
enums: baseStyleRules['comma-dangle'][1].arrays,
generics: baseStyleRules['comma-dangle'][1].arrays,
tuples: baseStyleRules['comma-dangle'][1].arrays,
},
],

'comma-spacing': 'off',
'@typescript-eslint/comma-spacing': baseStyleRules['comma-spacing'],

'default-param-last': 'off',
'@typescript-eslint/default-param-last': baseBestPracticesRules['default-param-last'],

'dot-notation': 'off',
'@typescript-eslint/dot-notation': baseBestPracticesRules['dot-notation'],

'func-call-spacing': 'off',
'@typescript-eslint/func-call-spacing': baseStyleRules['func-call-spacing'],

// ❌ Broken for some cases, but still useful.
// Here until Prettifier is used.
indent: 'off',
'@typescript-eslint/indent': baseStyleRules.indent,

'keyword-spacing': 'off',
'@typescript-eslint/keyword-spacing': baseStyleRules['keyword-spacing'],

'lines-between-class-members': 'off',
'@typescript-eslint/lines-between-class-members': baseStyleRules['lines-between-class-members'],

'no-array-constructor': 'off',
'@typescript-eslint/no-array-constructor': baseStyleRules['no-array-constructor'],

'no-dupe-class-members': 'off',
'@typescript-eslint/no-dupe-class-members': baseES6Rules['no-dupe-class-members'],

'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': baseBestPracticesRules['no-empty-function'],

'no-extra-parens': 'off',
'@typescript-eslint/no-extra-parens': baseErrorsRules['no-extra-parens'],

'no-extra-semi': 'off',
'@typescript-eslint/no-extra-semi': baseErrorsRules['no-extra-semi'],

// ❌ Fails due to missing parser
// 'no-implied-eval': 'off',
// 'no-new-func': 'off',
// '@typescript-eslint/no-implied-eval': baseBestPracticesRules['no-implied-eval'],

'no-loss-of-precision': 'off',
'@typescript-eslint/no-loss-of-precision': baseErrorsRules['no-loss-of-precision'],

'no-loop-func': 'off',
'@typescript-eslint/no-loop-func': baseBestPracticesRules['no-loop-func'],

'no-magic-numbers': 'off',
'@typescript-eslint/no-magic-numbers': baseBestPracticesRules['no-magic-numbers'],

'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': baseBestPracticesRules['no-redeclare'],

// ESLint variant does not work with TypeScript enums.
'no-shadow': 'off',
'@typescript-eslint/no-shadow': baseVariablesRules['no-shadow'],

'no-throw-literal': 'off',
'@typescript-eslint/no-throw-literal': baseBestPracticesRules['no-throw-literal'],

'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': baseBestPracticesRules['no-unused-expressions'],

'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': baseVariablesRules['no-unused-vars'],

// https://erkinekici.com/articles/linting-trap#no-use-before-define
// 'no-use-before-define': 'off',
// '@typescript-eslint/no-use-before-define': baseVariablesRules['no-use-before-define'],

// ESLint variant does not understand TypeScript constructors.
// eslint/eslint/#14118, typescript-eslint/typescript-eslint#873
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': baseES6Rules['no-useless-constructor'],

quotes: 'off',
'@typescript-eslint/quotes': baseStyleRules.quotes,

semi: 'off',
'@typescript-eslint/semi': baseStyleRules.semi,

'space-before-function-paren': 'off',
'@typescript-eslint/space-before-function-paren': baseStyleRules['space-before-function-paren'],

'require-await': 'off',
'@typescript-eslint/require-await': baseBestPracticesRules['require-await'],

'no-return-await': 'off',
'@typescript-eslint/return-await': baseBestPracticesRules['no-return-await'],

'space-infix-ops': 'off',
'@typescript-eslint/space-infix-ops': baseStyleRules['space-infix-ops'],

'object-curly-spacing': 'off',
'@typescript-eslint/object-curly-spacing': baseStyleRules['object-curly-spacing'],

'import/extensions': [
baseImportsRules['import/extensions'][0],
baseImportsRules['import/extensions'][1],
{
...baseImportsRules['import/extensions'][2],
ts: 'never',
tsx: 'never',
},
],

// Changes required is not yet implemented:
// 'import/no-extraneous-dependencies': [
// baseImportsRules['import/no-extraneous-dependencies'][0],
// {
// ...baseImportsRules['import/no-extraneous-dependencies'][1],
// devDependencies: baseImportsRules[
// 'import/no-extraneous-dependencies'
// ][1].devDependencies.reduce((result, devDep) => {
// const toAppend = [devDep];
// const devDepWithTs = devDep.replace(/\bjs(x?)\b/g, 'ts$1');
// if (devDepWithTs !== devDep) {
// toAppend.push(devDepWithTs);
// }
// return [...result, ...toAppend];
// }, []),
// },
// ],
};
}

function getAliasesFromTsConfig() {
return Object.keys(tsconfigJson.compilerOptions.paths)
.map((path) => `${path}*`);
Expand Down
7 changes: 7 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ You could run other types of tests as well, but they may take longer time and ov
- Build desktop application: `npm run electron:build`
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`

### Utility Scripts

- Run fresh NPM install: [`./scripts/fresh-npm-install.sh`](../scripts/fresh-npm-install.sh)
- This script provides a clean NPM install, removing existing node modules and optionally the package-lock.json (when run with -n), then installs dependencies and runs unit tests.
- Configure VSCode: [`./scripts/configure-vscode.sh`](../scripts/configure-vscode.sh)
- This script checks and sets the necessary configurations for VSCode in `settings.json` file.

## Recommended extensions

You should use EditorConfig to follow project style.
Expand Down
Loading

0 comments on commit ff84f56

Please sign in to comment.