Skip to content

Commit

Permalink
🧹 chore: add ESLint
Browse files Browse the repository at this point in the history
  • Loading branch information
ShayanTheNerd committed Jul 28, 2024
1 parent 573271f commit a6bf38e
Show file tree
Hide file tree
Showing 27 changed files with 5,335 additions and 2,754 deletions.
8 changes: 7 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
{
"recommendations": ["astro-build.astro-vscode", "csstools.postcss", "esbenp.prettier-vscode"]
/* prettier-ignore */
"recommendations": [
"csstools.postcss",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"astro-build.astro-vscode"
]
}
39 changes: 38 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
{
"prettier.documentSelectors": ["**/*.astro"],
"[astro]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }
"[astro]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },

"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never" // Prevent conflicts with “perfectionist/sort-imports” rule.
},

/* Silent stylistic rules in the editor, but still auto fix them. */
"eslint.rules.customizations": [
{ "rule": "*sort*", "severity": "off" },
{ "rule": "*style*", "severity": "off" },
{ "rule": "*indent", "severity": "off" },
{ "rule": "*quotes", "severity": "off" },
{ "rule": "import-*", "severity": "off" },
{ "rule": "*console", "severity": "off" },
{ "rule": "*-spaces", "severity": "off" },
{ "rule": "*-spacing", "severity": "off" },
{ "rule": "*newline*", "severity": "off" },
{ "rule": "attribute*", "severity": "off" },
{ "rule": "import/first", "severity": "off" },
{ "rule": "format/prettier", "severity": "off" }
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"gql",
"graphql"
]
}
318 changes: 318 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
import eslintJS from '@eslint/js';
import eslintAntfuConfig from '@antfu/eslint-config';
import eslintPluginVitest from 'eslint-plugin-vitest';
import eslintPluginStylistic from '@stylistic/eslint-plugin';

/* eslint-disable no-magic-numbers -- Improve SNR */
const jsRules = {
...eslintJS.configs.recommended.rules,

/* Possible Problems */
'no-await-in-loop': 'error',
'no-self-compare': 'error',
'no-unreachable-loop': 'error',
'no-inner-declarations': 'error',
'array-callback-return': 'error',
'no-useless-assignment': 'error',
'no-constructor-return': 'error',
'require-atomic-updates': 'error',
'no-async-promise-executor': 'error',
'no-template-curly-in-string': 'error',
'no-promise-executor-return': 'error',
'no-unmodified-loop-condition': 'error',
'no-use-before-define': ['error', 'nofunc'],
'use-isnan': ['error', { enforceForIndexOf: true }],
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'no-unsafe-negation': ['error', { enforceForOrderingRelations: true }],
'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }],

/* Suggestions */
'yoda': 'error',
'strict': 'error',
'no-var': 'error',
'eqeqeq': 'error',
'no-new': 'error',
'no-eval': 'error',
'no-void': 'error',
'new-cap': 'error',
'no-proto': 'error',
'no-caller': 'error',
'no-empty': 'error',
'no-eq-null': 'error',
'camelcase': 'error',
'sort-imports': 'off',
'no-redeclare': 'off',
'complexity': 'error',
'no-plusplus': 'error',
'no-iterator': 'error',
'no-continue': 'error',
'no-lonely-if': 'error',
'max-params': 'error',
'no-shadow': ['error'],
'no-label-var': 'error',
'no-new-func': 'error',
'no-multi-str': 'error',
'guard-for-in': 'error',
'no-loop-func': 'error',
'default-case': 'error',
'no-script-url': 'error',
'prefer-const': 'error',
'no-undefined': 'error',
'no-undef-init': 'error',
'require-await': 'error',
'no-extra-bind': 'error',
'prefer-spread': 'error',
'no-lone-blocks': 'error',
'no-extra-label': 'error',
'accessor-pairs': 'error',
'no-useless-call': 'error',
'max-depth': ['error', 3],
'no-implied-eval': 'error',
'consistent-this': 'error',
'no-octal-escape': 'error',
'no-throw-literal': 'error',
'prefer-template': 'error',
'init-declarations': 'error',
'no-new-wrappers': 'error',
'block-scoped-var': 'error',
'no-extend-native': 'error',
'default-case-last': 'error',
'object-shorthand': 'error',
'no-useless-return': 'error',
'consistent-return': 'error',
'no-useless-concat': 'error',
'no-nested-ternary': 'error',
'no-useless-rename': 'error',
'no-implicit-globals': 'error',
'default-param-last': 'error',
'symbol-description': 'error',
'curly': ['error', 'multi-line'],
'prefer-rest-params': 'error',
'no-implicit-coercion': 'error',
'radix': ['error', 'as-needed'],
'func-name-matching': 'error',
'operator-assignment': 'error',
'no-unneeded-ternary': 'error',
'no-array-constructor': 'error',
'prefer-destructuring': 'error',
'no-underscore-dangle': 'error',
'prefer-object-spread': 'error',
'no-object-constructor': 'error',
'prefer-object-has-own': 'error',
'no-useless-constructor': 'error',
'class-methods-use-this': 'error',
'require-unicode-regexp': 'error',
'prefer-numeric-literals': 'error',
'no-useless-computed-key': 'error',
'max-nested-callbacks': ['error', 3],
'no-return-assign': ['error', 'always'],
'prefer-named-capture-group': 'error',
'no-bitwise': ['error', { int32Hint: true }],
'prefer-exponentiation-operator': 'error',
'import/extensions': ['error', 'ignorePackages'],
'dot-notation': ['error', { allowKeywords: false }],
'logical-assignment-operators': ['error', 'always'],
'no-sequences': ['error', { allowInParentheses: false }],
'no-multi-assign': ['error', { ignoreNonDeclaration: true }],
'no-empty-function': ['error', { allow: ['arrowFunctions'] }],
'prefer-arrow-callback': ['error', { allowUnboundThis: true }],
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }],
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
'no-extra-boolean-cast': ['error', { enforceForInnerExpressions: true }],
'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
'arrow-body-style': ['error', 'as-needed', { requireReturnForObjectLiteral: true }],
'no-restricted-exports': ['error', {
restrictDefaultExports: {
named: true,
namedFrom: true,
defaultFrom: true,
namespaceFrom: true,
},
}],
'no-magic-numbers': ['error', {
enforceConst: true,
ignoreDefaultValues: true,
ignoreClassFieldInitialValues: true,
ignore: [-100, -1, 0, 1, 2, 100],
}],
};

const tsRules = {
'ts/no-misused-promises': 'off',
'ts/no-unsafe-assignment': 'off',
'ts/strict-boolean-expressions': 'off',
'ts/consistent-type-definitions': ['error', 'type'],
};

const vitestRules = {
...eslintPluginVitest.configs.recommended.rules,

'vitest/prefer-todo': 'error',
'vitest/require-hook': 'error',
'vitest/prefer-to-be': 'error',
'vitest/prefer-spy-on': 'error',
'vitest/no-mocks-import': 'error',
'vitest/no-test-prefixes': 'error',
'vitest/no-alias-methods': 'error',
'vitest/no-focused-tests': 'error',
'vitest/no-disabled-tests': 'error',
'vitest/prefer-to-contain': 'error',
'vitest/consistent-test-it': 'error',
'vitest/prefer-called-with': 'error',
'vitest/prefer-to-be-falsy': 'error',
'vitest/no-duplicate-hooks': 'error',
'vitest/prefer-strict-equal': 'error',
'vitest/no-conditional-tests': 'error',
'vitest/prefer-to-be-truthy': 'error',
'vitest/prefer-to-be-object': 'error',
'vitest/no-standalone-expect': 'error',
'vitest/no-conditional-expect': 'error',
'vitest/no-conditional-in-test': 'error',
'vitest/prefer-to-have-length': 'error',
'vitest/prefer-hooks-in-order': 'error',
'vitest/prefer-lowercase-title': 'error',
'vitest/prefer-equality-matcher': 'error',
'vitest/consistent-test-filename': 'error',
'vitest/no-test-return-statement': 'error',
'vitest/require-to-throw-message': 'error',
'vitest/require-top-level-describe': 'error',
'vitest/prefer-comparison-matcher': 'error',
'vitest/no-interpolation-in-snapshots': 'error',
'vitest/prefer-mock-promise-shorthand': 'error',
'vitest/prefer-snapshot-hint': ['error', 'always'],
'vitest/max-nested-describe': ['error', { max: 1 }],
};

const stylisticRules = {
...eslintPluginStylistic.configs['recommended-flat'].rules,

'style/semi-style': 'error',
'style/no-extra-semi': 'error',
'style/spaced-comment': 'off',
'style/indent': ['error', 'tab'],
'style/type-annotation-spacing': 'error',
'style/arrow-parens': ['error', 'always'],
'style/indent-binary-ops': ['error', 'tab'],
'style/operator-linebreak': ['error', 'none'],
'style/implicit-arrow-linebreak': ['error', 'beside'],
'style/no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
'style/brace-style': ['error', '1tbs', { allowSingleLine: true }],
'style/semi': ['error', 'always', { omitLastInOneLineBlock: true }],
'style/lines-around-comment': ['error', {
allowTypeStart: true,
allowEnumStart: true,
allowClassStart: true,
allowBlockStart: true,
allowArrayStart: true,
allowModuleStart: true,
allowObjectStart: true,
allowInterfaceStart: true,
}],
'style/member-delimiter-style': ['error', {
multilineDetection: 'brackets',
multiline: { delimiter: 'semi', requireLast: true },
singleline: { delimiter: 'semi', requireLast: false },
}],
'style/padding-line-between-statements': [
'error',
{
prev: '*',
next: [
'do',
'try',
'for',
'iife',
'with',
'class',
'block',
'while',
'throw',
'return',
'switch',
'export',
'function',
'directive',
'block-like',
'cjs-export',
'multiline-block-like',
],
blankLine: 'always',
},
{
prev: 'export',
next: 'export',
blankLine: 'any',
},
{
prev: ['const', 'let', 'var'],
next: 'block-like',
blankLine: 'any',
},
{
prev: 'block-like',
next: '*',
blankLine: 'always',
},
{
prev: 'function-overload',
next: 'function',
blankLine: 'never',
},
],
};

const generalRules = {
'import/order': 'off',
'style/no-tabs': 'off',
'antfu/if-newline': 'off',
'unused-imports/no-unused-vars': 'off',

/* Sorting */
'perfectionist/sort-maps': ['error', { type: 'line-length' }],
'perfectionist/sort-exports': ['error', { type: 'line-length' }],
'perfectionist/sort-union-types': ['error', { type: 'line-length' }],
'perfectionist/sort-array-includes': ['error', { type: 'line-length' }],
'perfectionist/sort-intersection-types': ['error', { type: 'line-length' }],
'perfectionist/sort-named-imports': ['error', { type: 'line-length', groupKind: 'types-first' }],
'perfectionist/sort-named-exports': ['error', { type: 'line-length', groupKind: 'types-first' }],
'perfectionist/sort-imports': ['error', {
type: 'line-length',
internalPattern: ['@ts/**', '@styles/**', '@components/**'],
groups: [
['side-effect-style', 'side-effect'],
['index-type', 'builtin-type', 'external-type', 'internal-type', 'parent-type', 'sibling-type'],
['index', 'builtin', 'external', 'internal', 'parent', 'sibling'],
['object', 'unknown'],
],
}],
};

export default eslintAntfuConfig(
{
files: ['**/*.js', '**/*.ts'],
vue: false,
typescript: {
tsconfigPath: 'tsconfig.json',
},
// @ts-ignore: TypeScript can't properly infer the types.
rules: { ...jsRules, ...tsRules, ...stylisticRules },
},
{
files: ['src/tests/**'],
plugins: { eslintPluginVitest },
settings: {
vitest: {
typecheck: true,
},
},
languageOptions: {
globals: {
...eslintPluginVitest.environments.env.globals,
},
},
rules: { ...vitestRules },
},
{ rules: generalRules },
{ ignores: ['**/*.json', 'src/env.d.ts'] },
);
Loading

0 comments on commit a6bf38e

Please sign in to comment.