Skip to content

Instantly share code, notes, and snippets.

@darvid
Last active November 9, 2024 06:12
Show Gist options
  • Save darvid/03f41b66de2d7560f3aff136846f24c5 to your computer and use it in GitHub Desktop.
Save darvid/03f41b66de2d7560f3aff136846f24c5 to your computer and use it in GitHub Desktop.
πŸ’… eslint
{
"bracketSameLine": false,
"bracketSpacing": true,
"plugins": [
"prettier-plugin-pkg",
"prettier-plugin-sh",
"prettier-plugin-css-order",
"prettier-plugin-tailwindcss"
],
"printWidth": 80,
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false
}
import type { Linter } from "eslint";
import type { ConfigWithExtends } from "typescript-eslint";
import js from "@eslint/js";
import pluginImportAlias from "@limegrass/eslint-plugin-import-alias";
import tsParser from "@typescript-eslint/parser";
import eslintConfigPrettier from "eslint-config-prettier";
import eslintPluginJsonc from "eslint-plugin-jsonc";
// @ts-expect-error noImplicitAny
import jsxA11y from "eslint-plugin-jsx-a11y";
import perfectionist from "eslint-plugin-perfectionist";
// @ts-expect-error noImplicitAny
import pluginPreferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
import pluginPrettier from "eslint-plugin-prettier";
import pluginPrettierRecommended from "eslint-plugin-prettier/recommended";
import pluginReact from "eslint-plugin-react";
// @ts-expect-error noImplicitAny
import pluginReactHooks from "eslint-plugin-react-hooks";
// @ts-expect-error noImplicitAny
import pluginReactRefresh from "eslint-plugin-react-refresh";
import * as regexpPlugin from "eslint-plugin-regexp";
import pluginTsdoc from "eslint-plugin-tsdoc";
import pluginUnusedImports from "eslint-plugin-unused-imports";
import globals from "globals";
import tseslint, { configs as tseslintConfigs } from "typescript-eslint";
export default tseslint.config(
...["js", "ts"].map<ConfigWithExtends>((lang) => ({
files: [`*.config.${lang}`, `**/*.{${lang},m${lang},${lang}x,m${lang}x}`],
languageOptions: {
ecmaVersion: "latest" as const,
globals: {
...globals.browser,
},
parser: tsParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
tsconfigRootDir: import.meta.dirname,
},
sourceType: "module",
},
plugins: {
importAlias: pluginImportAlias,
perfectionist,
"prefer-arrow-functions": pluginPreferArrowFunctions,
},
rules: {
"func-style": ["error", "expression"],
"import/first": "error",
"import/order": "off",
"importAlias/import-alias": "error",
"perfectionist/sort-imports": [
"error",
{
customGroups: { type: {}, value: {} },
environment: "node",
groups: [
"type",
["builtin", "external"],
"internal-type",
"internal",
["parent-type", "sibling-type", "index-type"],
["parent", "sibling", "index"],
"object",
"unknown",
],
ignoreCase: true,
internalPattern: ["@/**"],
matcher: "minimatch",
maxLineLength: 80,
newlinesBetween: "always",
order: "asc",
specialCharacters: "keep",
type: "alphabetical",
},
],
"prefer-arrow/prefer-arrow-functions": [
"error",
{
classPropertiesAllowed: false,
disallowPrototype: true,
singleReturnOnly: false,
},
],
"sort-imports": "off",
},
...perfectionist.configs["recommended-natural"],
})),
// React: https://github.com/jsx-eslint/eslint-plugin-react/#shareable-configs
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
ignores: ["**/components/ui/*.tsx"],
settings: {
react: {
version: "detect",
},
},
...(pluginReact.configs.flat?.recommended as ConfigWithExtends),
plugins: {
...(pluginReact.configs.flat?.recommended as ConfigWithExtends).plugins,
"react-hooks": pluginReactHooks,
"react-refresh": pluginReactRefresh,
},
rules: {
...(pluginReactHooks.configs.recommended
.rules as Partial<Linter.RulesRecord>),
// https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#eslint
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off",
"react-refresh/only-export-components": "warn",
},
},
// Globals
{
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
languageOptions: {
globals: {
...globals.serviceworker,
...globals.browser,
},
},
},
// Import resolver
{
files: ["./**/*.{ts,mts,tsx,mtsx}"],
settings: {
"import/resolver": {
node: true,
typescript: true,
},
},
...tseslintConfigs.recommendedTypeChecked,
},
// JS
{
files: ["**/*.{js,mjs,jsx}"],
...js.configs.recommended,
...tseslintConfigs.disableTypeChecked,
},
// JSON
...eslintPluginJsonc.configs["flat/prettier"],
...eslintPluginJsonc.configs["flat/recommended-with-jsonc"],
...eslintPluginJsonc.configs["flat/recommended-with-json5"],
...eslintPluginJsonc.configs["flat/recommended-with-json"].map((config) => ({
...config,
ignores: ["**/.vscode/*.json", "tsconfig*.json"],
})),
// Prettier
eslintConfigPrettier,
{
files: ["**/*.{ts,mts,tsx,mtsx}"],
plugins: {
prettier: pluginPrettier,
},
...pluginPrettierRecommended,
rules: {
...pluginPrettierRecommended.rules,
},
},
// TSDoc
{
files: ["**/*.{ts,mts,tsx,mtsx}"],
plugins: {
tsdoc: pluginTsdoc,
},
rules: {
"tsdoc/syntax": "error",
},
},
// Regex
regexpPlugin.configs["flat/recommended"],
// JSX Accessibility
jsxA11y.flatConfigs.recommended,
// Unused imports
{
files: ["**/*.{ts,mts,tsx,mtsx}"],
plugins: {
"unused-imports": pluginUnusedImports,
},
rules: {
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
args: "after-used",
argsIgnorePattern: "^_",
vars: "all",
varsIgnorePattern: "^_",
},
],
},
},
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment