UNPKG

@refinist/eslint-config

Version:
324 lines (315 loc) 9.52 kB
import { GLOB_ALL_SRC, GLOB_ASTRO_TS, GLOB_CSS, GLOB_DIST, GLOB_EXCLUDE, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_NODE_MODULES, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_YAML } from "./globs-BnHr61hi.js"; import tseslint from "typescript-eslint"; import pluginVue from "eslint-plugin-vue"; import pluginPrettier from "eslint-plugin-prettier"; import pluginIgnore from "eslint-config-flat-gitignore"; import pluginPrettierRecommended from "eslint-plugin-prettier/recommended"; import pluginStylistic from "@stylistic/eslint-plugin"; import configJs from "@eslint/js"; import * as parserVue from "vue-eslint-parser"; import globals from "globals"; import { isPackageExists } from "local-pkg"; //#region src/configs/ignores.ts const ignores = () => [{ ignores: GLOB_EXCLUDE, name: "refinist/global-ignores" }, { ...pluginIgnore({ strict: false }), name: "refinist/gitignore" }]; //#endregion //#region src/configs/javascript.ts const restrictedSyntaxJs = [ "ForInStatement", "LabeledStatement", "WithStatement" ]; const javascript = () => [{ ...configJs.configs.recommended, name: "refinist/js/recommended" }, { languageOptions: { globals: { ...globals.browser, ...globals.es2021, ...globals.node }, parserOptions: { ecmaFeatures: { jsx: true }, sourceType: "module" }, sourceType: "module" }, name: "refinist/js", rules: { "array-callback-return": "error", "block-scoped-var": "error", "dot-notation": "warn", eqeqeq: ["error", "smart"], "no-alert": "warn", "no-console": ["warn", { allow: [ "warn", "error", "info", "clear" ] }], "no-debugger": "warn", "no-duplicate-imports": "error", "no-empty": ["error", { allowEmptyCatch: true }], "no-fallthrough": ["warn", { commentPattern: String.raw`break[\s\w]*omitted` }], "no-inner-declarations": "error", "no-lonely-if": "error", "no-multi-str": "error", "no-restricted-syntax": ["error", ...restrictedSyntaxJs], "no-unused-expressions": ["error", { allowShortCircuit: true, allowTaggedTemplates: true, allowTernary: true }], "no-unused-vars": "off", "no-void": "error", "object-shorthand": [ "error", "always", { avoidQuotes: true, ignoreConstructors: false } ], "prefer-arrow-callback": ["error", { allowNamedFunctions: false, allowUnboundThis: true }], "prefer-const": ["warn", { destructuring: "all", ignoreReadBeforeAssign: true }], "prefer-exponentiation-operator": "error", "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }], "prefer-rest-params": "error", "prefer-spread": "error", "prefer-template": "error", "require-await": "error", "unicode-bom": ["error", "never"], "use-isnan": ["error", { enforceForIndexOf: true, enforceForSwitchCase: true }], "valid-typeof": ["error", { requireStringLiterals: true }], "vars-on-top": "error" } }]; //#endregion //#region src/configs/prettier.ts const rules = { ...pluginPrettierRecommended.rules }; delete rules["vue/html-self-closing"]; const prettier = () => [{ name: "refinist/prettier", plugins: { prettier: pluginPrettier }, rules: { ...rules, "prettier/prettier": "warn" } }]; //#endregion //#region src/configs/stylistic.ts const stylistic = () => [{ name: "refinist/stylistic", plugins: { "@stylistic": pluginStylistic }, rules: { "@stylistic/spaced-comment": [ "error", "always", { block: { balanced: true } } ] } }]; //#endregion //#region src/configs/typescript.ts const typescriptCore = ({ typeAware = false } = {}) => tseslint.config({ extends: [...typeAware ? tseslint.configs.recommendedTypeChecked : tseslint.configs.recommended], ...typeAware ? { languageOptions: { parserOptions: { projectService: true, tsconfigRootDir: process.cwd() } } } : void 0, files: [GLOB_TS, GLOB_TSX], name: "refinist/typescript", rules: { "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "as", objectLiteralTypeAssertions: "allow-as-parameter" }], "@typescript-eslint/consistent-type-imports": ["error", { disallowTypeAnnotations: false, fixStyle: "inline-type-imports" }], "@typescript-eslint/method-signature-style": ["error", "property"], "@typescript-eslint/no-empty-object-type": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-import-type-side-effects": "error", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-redeclare": "error", "@typescript-eslint/no-unsafe-function-type": "off", "@typescript-eslint/no-unused-expressions": ["error", { allowShortCircuit: true, allowTaggedTemplates: true, allowTernary: true }], "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/prefer-as-const": "warn", "@typescript-eslint/prefer-literal-enum-member": ["error", { allowBitwiseExpressions: true }], "no-restricted-syntax": [ "error", ...restrictedSyntaxJs, "TSEnumDeclaration[const=true]" ] } }); const typescript = ({ typeAware = false } = {}) => [ ...typescriptCore({ typeAware }), { files: ["**/*.d.ts"], name: "refinist/typescript/dts-rules", rules: { "eslint-comments/no-unlimited-disable": "off", "import/no-duplicates": "off", "no-restricted-syntax": "off", "unused-imports/no-unused-vars": "off" } }, { files: [GLOB_JS, "**/*.cjs"], name: "refinist/typescript/cjs-rules", rules: { "@typescript-eslint/no-require-imports": "off" } } ]; //#endregion //#region src/configs/vue.ts const reactivityTransform = () => [{ languageOptions: { globals: { $: "readonly", $$: "readonly", $computed: "readonly", $customRef: "readonly", $ref: "readonly", $shallowRef: "readonly", $toRef: "readonly" } }, name: "refinist/vue/reactivity-transform", plugins: { vue: pluginVue }, rules: { "vue/no-setup-props-reactivity-loss": "off" } }]; const vueTs = typescriptCore().filter((config) => config.name !== "typescript-eslint/base").map((config) => { return { ...config, files: [GLOB_VUE], name: `refinist/vue/${config.name?.replace("refinist/", "") || "anonymous"}` }; }); const recommendedRules = pluginVue.configs["flat/recommended"].map((c) => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}); const vue = () => [ ...vueTs, { files: [GLOB_VUE], languageOptions: { parser: parserVue, parserOptions: { ecmaFeatures: { jsx: true }, extraFileExtensions: [".vue"], parser: tseslint.parser, sourceType: "module" } }, name: "refinist/vue", plugins: { "@typescript-eslint": tseslint.plugin, vue: pluginVue }, processor: pluginVue.processors[".vue"], rules: { ...recommendedRules, "vue/block-order": ["error", { order: [ "script", "template", "style" ] }], "vue/custom-event-name-casing": ["error", "camelCase"], "vue/eqeqeq": ["error", "smart"], "vue/html-self-closing": ["error", { html: { component: "always", normal: "always", void: "any" }, math: "always", svg: "always" }], "vue/max-attributes-per-line": "off", "vue/multi-word-component-names": "off", "vue/no-constant-condition": "warn", "vue/no-empty-pattern": "error", "vue/no-loss-of-precision": "error", "vue/no-unused-refs": "error", "vue/no-useless-v-bind": "error", "vue/no-v-html": "off", "vue/object-shorthand": [ "error", "always", { avoidQuotes: true, ignoreConstructors: false } ], "vue/one-component-per-file": "off", "vue/padding-line-between-blocks": ["error", "always"], "vue/prefer-template": "error", "vue/require-default-prop": "off", "vue/require-prop-types": "off" } }, ...reactivityTransform() ]; //#endregion //#region src/env.ts const hasTypeScript = () => isPackageExists("typescript"); const hasVue = () => [ "vue", "nuxt", "vitepress", "@slidev/cli" ].some((i) => isPackageExists(i)); const hasReact = () => [ "react", "react-dom", "react-router", "@remix-run/node", "@remix-run/react", "@remix-run/serve", "@remix-run/dev", "@react-router/node", "@react-router/react", "@react-router/serve", "@react-router/dev", "next" ].some((i) => isPackageExists(i)); //#endregion //#region src/presets.ts const presetBasic = ({ typeAware = false } = {}) => [ ...ignores(), ...javascript(), ...stylistic(), ...typescript({ typeAware }) ]; function refinist(options = {}, ...userConfigs) { const { vue: enableVue = hasVue(), prettier: enablePrettier = true } = options; const _userConfigs = [...userConfigs.flat()]; const hasReact$1 = _userConfigs.some((_) => _.name?.includes("refinist/react")); const configs = [...presetBasic({ typeAware: hasReact$1 })]; if (enableVue) configs.push(...vue()); if (enablePrettier) configs.push(...prettier()); return [...configs, ..._userConfigs]; } //#endregion export { GLOB_ALL_SRC, GLOB_ASTRO_TS, GLOB_CSS, GLOB_DIST, GLOB_EXCLUDE, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_LOCKFILE, GLOB_MARKDOWN, GLOB_NODE_MODULES, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_YAML, configJs, hasReact, hasTypeScript, hasVue, ignores, javascript, parserVue, pluginIgnore, pluginPrettier, pluginPrettierRecommended, pluginStylistic, pluginVue, prettier, reactivityTransform, refinist, restrictedSyntaxJs, stylistic, tseslint, typescript, typescriptCore, vue };