@modyqyw/fabric
Version:
Opinionated shareable specifications for git-based JavaScript/TypeScript projects.
1,377 lines (1,359 loc) • 115 kB
JavaScript
import { i as interopDefault, a as isBoolean } from './fabric.Cj4waNRr.mjs';
import { a as GLOB_SCRIPT, r as GLOB_VUE, d as GLOB_DTS, e as GLOB_TS, f as GLOB_TSX, C as GLOB_EXCLUDE, l as GLOB_JSON, m as GLOB_JSON5, n as GLOB_JSONC, q as GLOB_MARKDOWN, v as GLOB_MARKDOWN_SCRIPT, w as GLOB_MARKDOWN_VUE, c as GLOB_JSX, o as GLOB_TOML, p as GLOB_YAML } from './fabric.DrBYK7XE.mjs';
import { h as hasTypeScript, k as hasVue, b as hasNuxt3, o as hasRemix, p as hasReactRouter, n as hasNext, J as hasVite, m as hasVue3, D as hasMiniProgram, u as hasReact, q as hasReactNative, a as hasNuxt, I as hasTailwindCss, G as hasUnoCss } from './fabric.UWmAURsN.mjs';
import { fixupPluginRules } from '@eslint/compat';
import * as _configGitignore from 'eslint-config-flat-gitignore';
import * as _parserBabel from '@babel/eslint-parser';
import * as _parserTypeScript from '@typescript-eslint/parser';
import * as _pluginTypeScript from '@typescript-eslint/eslint-plugin';
import * as _configCommand from 'eslint-plugin-command/config';
import * as _pluginJsdoc from 'eslint-plugin-jsdoc';
import * as _pluginImportX from 'eslint-plugin-import-x';
import * as _importResolverOxc from 'eslint-import-resolver-oxc';
import * as _pluginUnusedImports from 'eslint-plugin-unused-imports';
import * as _pluginNoBarrelFiles from 'eslint-plugin-no-barrel-files';
import * as _pluginPromise from 'eslint-plugin-promise';
import * as _pluginRegexp from 'eslint-plugin-regexp';
import * as _pluginN from 'eslint-plugin-n';
import _pluginPerfectionist from 'eslint-plugin-perfectionist';
import * as _pluginUnicorn from 'eslint-plugin-unicorn';
import * as _pluginReactX from 'eslint-plugin-react-x';
import * as _pluginReactDom from 'eslint-plugin-react-dom';
import * as _pluginReactWebApi from 'eslint-plugin-react-web-api';
import * as _pluginReactHooksExtra from 'eslint-plugin-react-hooks-extra';
import * as _pluginReactNamingConvention from 'eslint-plugin-react-naming-convention';
import * as _pluginReactHooks from 'eslint-plugin-react-hooks';
import * as _pluginReactPerf from 'eslint-plugin-react-perf';
import * as _pluginReactRefresh from 'eslint-plugin-react-refresh';
import * as _pluginReactNative from 'eslint-plugin-react-native';
import * as _pluginNext from '@next/eslint-plugin-next';
import * as _parserVue from 'vue-eslint-parser';
import * as _pluginVue from 'eslint-plugin-vue';
import * as _pluginVueScopedCss from 'eslint-plugin-vue-scoped-css';
import * as _pluginNuxt2 from 'eslint-plugin-nuxt';
import * as _pluginNuxt3 from '@nuxt/eslint-plugin';
import * as _pluginTailwindcss from 'eslint-plugin-tailwindcss';
import _pluginUnocss from '@unocss/eslint-plugin';
import * as _pluginMarkdown from 'eslint-plugin-markdown';
import * as _parserJsonc from 'jsonc-eslint-parser';
import * as _pluginJsonc from 'eslint-plugin-jsonc';
import * as _pluginPackageJson from 'eslint-plugin-package-json';
import * as _parserToml from 'toml-eslint-parser';
import * as _pluginToml from 'eslint-plugin-toml';
import * as _pluginYml from 'eslint-plugin-yml';
import * as _parserYml from 'yaml-eslint-parser';
import { defu } from 'defu';
import globals from 'globals';
const configGitignore = interopDefault(_configGitignore);
const parserBabel = interopDefault(_parserBabel);
const parserTypeScript = interopDefault(_parserTypeScript);
const pluginTypeScript = interopDefault(
_pluginTypeScript
);
const configCommand = interopDefault(_configCommand);
const pluginJsdoc = interopDefault(
_pluginJsdoc
);
const pluginImportX = interopDefault(
_pluginImportX
);
const importResolverOxc = interopDefault(_importResolverOxc);
const pluginUnusedImports = interopDefault(_pluginUnusedImports);
const pluginNoBarrelFiles = interopDefault(_pluginNoBarrelFiles);
const pluginPromise = interopDefault(
_pluginPromise
);
const pluginRegexp = interopDefault(
_pluginRegexp
);
const pluginN = interopDefault(_pluginN);
const pluginPerfectionist = interopDefault(
_pluginPerfectionist
);
const pluginUnicorn = interopDefault(
_pluginUnicorn
);
const pluginReactX = interopDefault(
_pluginReactX
);
const pluginReactDom = interopDefault(
_pluginReactDom
);
const pluginReactWebApi = interopDefault(
_pluginReactWebApi
);
const pluginReactHooksExtra = interopDefault(
_pluginReactHooksExtra
);
const pluginReactNamingConvention = interopDefault(
_pluginReactNamingConvention
);
const pluginReactHooks = fixupPluginRules(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
interopDefault(_pluginReactHooks)
);
const pluginReactPerf = fixupPluginRules(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
interopDefault(_pluginReactPerf)
);
const pluginReactRefresh = interopDefault(
_pluginReactRefresh
);
const pluginReactNative = fixupPluginRules(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
interopDefault(_pluginReactNative)
);
const pluginNext = interopDefault(
_pluginNext
);
const parserVue = interopDefault(_parserVue);
const pluginVue = interopDefault(_pluginVue);
const pluginVueScopedCss = interopDefault(
_pluginVueScopedCss
);
const pluginNuxt2 = interopDefault(
_pluginNuxt2
);
const pluginNuxt3 = interopDefault(
_pluginNuxt3
);
const pluginTailwindcss = interopDefault(
_pluginTailwindcss
);
const pluginUnocss = interopDefault(
_pluginUnocss
);
const pluginMarkdown = interopDefault(
_pluginMarkdown
);
const parserJsonc = interopDefault(_parserJsonc);
const pluginJsonc = interopDefault(
_pluginJsonc
);
const pluginPackageJson = interopDefault(
_pluginPackageJson
);
const parserToml = interopDefault(_parserToml);
const pluginToml = interopDefault(
_pluginToml
);
const parserYml = interopDefault(_parserYml);
const pluginYml = interopDefault(_pluginYml);
function barrel(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/imports",
files,
plugins: {
"no-barrel-files": pluginNoBarrelFiles
},
rules: {
"no-barrel-files/no-barrel-files": "error",
...rules
}
},
{
name: "base/imports/typescript",
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
function command(options = {}) {
return [
{
...configCommand(options),
name: "base/command"
}
];
}
function gitignore(options = {}) {
return [
{
...configGitignore(
defu(options, {
files: [".gitignore", ".eslintignore"],
strict: false
})
),
name: "ignores/gitignore"
}
];
}
function ignores(options = {}) {
return [
{
name: "ignores/base",
ignores: options.ignores ?? GLOB_EXCLUDE
}
];
}
function imports(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/imports",
files,
plugins: {
import: pluginImportX
},
rules: {
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/export.md
"import/export": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/extensions.md
// https://vite.dev/guide/performance.html#reduce-resolve-operations
"import/extensions": [
"warn",
"ignorePackages",
{ checkTypeImports: true }
],
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-mutable-exports.md
"import/no-mutable-exports": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-named-as-default.md
"import/no-named-as-default": "warn",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-named-as-default-member.md
"import/no-named-as-default-member": "warn",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/default.md
"import/default": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/named.md
"import/named": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/namespace.md
"import/namespace": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-self-import.md
"import/no-self-import": "error",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-duplicates.md
"import/no-duplicates": "warn",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-unresolved.md
"import/no-unresolved": [
"error",
{
commonjs: true,
ignore: [
String.raw`^virtual\:`,
String.raw`^\~`,
String.raw`^\@`,
String.raw`^windi\:`,
String.raw`windi\.css`,
String.raw`^uno\:`,
String.raw`uno\.css`,
"vue-router/auto",
"vue-router/auto-routes",
"@intlify/unplugin-vue-i18n"
]
}
],
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/order.md
"import/order": [
"error",
{
groups: [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
"object",
"type"
],
pathGroups: [
{
pattern: "~/**",
group: "internal"
},
{
pattern: "~~/**",
group: "internal"
},
{
pattern: "@/**",
group: "internal"
},
{
pattern: "@@/**",
group: "internal"
}
]
}
],
...rules
},
settings: {
// https://github.com/un-ts/eslint-plugin-import-x#import-xcore-modules
"import/core-modules": ["electron"],
// https://github.com/un-ts/eslint-plugin-import-x#import-xextensions
"import/extensions": [".js", ".cjs", ".mjs", ".jsx"],
// https://github.com/un-ts/eslint-plugin-import-x#import-xignore
"import/ignore": [
"node_modules",
String.raw`\.(scss|sass|less|css|svg|json)$`
],
// https://github.com/un-ts/eslint-plugin-import-x#resolvers
"import/resolver": "oxc"
}
},
{
name: "base/imports/typescript",
files: typescriptFiles,
rules: {
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-named-as-default-member.md
// https://typescript-eslint.io/troubleshooting/typed-linting/performance/#eslint-plugin-import
"import/no-named-as-default-member": "off",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/default.md
// https://typescript-eslint.io/troubleshooting/typed-linting/performance/#eslint-plugin-import
"import/default": "off",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/named.md
// https://typescript-eslint.io/troubleshooting/typed-linting/performance/#eslint-plugin-import
"import/named": "off",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/namespace.md
// https://typescript-eslint.io/troubleshooting/typed-linting/performance/#eslint-plugin-import
"import/namespace": "off",
// https://github.com/un-ts/eslint-plugin-import-x/blob/v4.6.1/docs/rules/no-unresolved.md
// See https://github.com/iamturns/eslint-config-airbnb-typescript#why-is-importno-unresolved-disabled
"import/no-unresolved": "off",
...typescriptRules
},
settings: {
// https://github.com/un-ts/eslint-plugin-import-x#import-xextensions
"import/extensions": [
".js",
".cjs",
".mjs",
".jsx",
".ts",
".cts",
".mts",
".tsx",
".d.ts"
],
// https://github.com/un-ts/eslint-plugin-import-x#import-xparsers
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".cts", ".mts", ".tsx", ".d.ts"]
},
// https://github.com/un-ts/eslint-plugin-import-x#resolvers
"import/resolver": "oxc"
}
}
];
}
function javascript(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
parserOptions = {},
languageOptions = {}
} = options;
return [
{
name: "languages/javascript",
files,
languageOptions: {
ecmaVersion: "latest",
globals: {
...globals.browser,
...globals.es2025,
...globals.node,
dd: "readonly",
// https://open.dingtalk.com/
jd: "readonly",
// https://mp.jd.com/
ks: "readonly",
// https://mp.kuaishou.com/
my: "readonly",
// https://opendocs.alipay.com/mini
plus: "readonly",
// http://www.html5plus.org/doc/h5p.html
qh: "readonly",
// https://mp.360.cn/
qq: "readonly",
// https://q.qq.com/
swan: "readonly",
// https://smartprogram.baidu.com/docs
tt: "readonly",
// https://developer.open-douyin.com/ https://open.feishu.cn/
uni: "readonly",
// https://uniapp.dcloud.io/
uniCloud: "readonly",
// https://uniapp.dcloud.io
weex: "readonly",
// https://weex.apache.org/
wx: "readonly"
// https://developers.weixin.qq.com/miniprogram/dev/framework/
},
parser: parserBabel,
parserOptions: {
ecmaFeatures: {
globalReturn: false,
jsx: true
},
ecmaVersion: "latest",
requireConfigFile: false,
sourceType: "module",
...parserOptions
},
sourceType: "module",
...languageOptions
},
linterOptions: {
reportUnusedDisableDirectives: true
},
rules: {
// https://github.com/eslint/eslint/blob/main/packages/js/src/configs/eslint-recommended.js
"constructor-super": "error",
"for-direction": "error",
"getter-return": "error",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-const-assign": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-args": "error",
"no-dupe-class-members": "error",
"no-dupe-else-if": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "error",
"no-func-assign": "error",
"no-global-assign": "error",
"no-import-assign": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-new-native-nonconstructor": "error",
"no-nonoctal-decimal-escape": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-prototype-builtins": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-setter-return": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
"no-undef": "error",
// 'no-unexpected-multiline': 'error', // Conflicts with Prettier.
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unsafe-negation": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-unused-vars": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-with": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error",
// https://eslint.org/docs/latest/rules/no-array-constructor
// Comes with https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v55.0.0/docs/rules/no-new-array.md.
"no-array-constructor": "error",
// https://eslint.org/docs/latest/rules/no-console
// Use consola, pino, winston, etc.
"no-console": "warn",
// https://eslint.org/docs/latest/rules/no-eval
"no-eval": "error",
// https://eslint.org/docs/latest/rules/no-implied-eval
"no-implied-eval": "error",
// https://eslint.org/docs/latest/rules/no-lonely-if
// Comes with https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v55.0.0/docs/rules/no-lonely-if.md.
"no-lonely-if": "error",
// https://eslint.org/docs/latest/rules/no-shadow
"no-shadow": "warn",
// https://eslint.org/docs/latest/rules/no-throw-literal
"no-throw-literal": "error",
// https://eslint.org/docs/latest/rules/no-use-before-define
"no-use-before-define": "warn",
// https://eslint.org/docs/latest/rules/no-var
"no-var": "error",
// https://eslint.org/docs/latest/rules/prefer-const
"prefer-const": "error",
// https://eslint.org/docs/latest/rules/prefer-promise-reject-errors
"prefer-promise-reject-errors": "off",
// https://eslint.org/docs/latest/rules/prefer-rest-params
"prefer-rest-params": "error",
// https://eslint.org/docs/latest/rules/prefer-spread
"prefer-spread": "error",
// https://eslint.org/docs/latest/rules/require-await
"require-await": "off",
...rules
}
}
];
}
function jsdoc(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/jsdoc",
files,
plugins: {
jsdoc: pluginJsdoc
},
rules: {
// https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.1/src/index.js#L298
// https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.1/src/index.js#L244-L261
"jsdoc/check-access": "warn",
// 'jsdoc/check-alignment': 'warn', // Conflicts with prettier
// 'jsdoc/check-examples': 'off',
// 'jsdoc/check-indentation': 'off',
// 'jsdoc/check-line-alignment': 'off',
"jsdoc/check-param-names": "warn",
"jsdoc/check-property-names": "warn",
// 'jsdoc/check-syntax': 'off',
"jsdoc/check-tag-names": "warn",
// 'jsdoc/check-template-names': 'off',
"jsdoc/check-types": "warn",
"jsdoc/check-values": "warn",
// 'jsdoc/convert-to-jsdoc-comments': 'off',
"jsdoc/empty-tags": "warn",
"jsdoc/implements-on-classes": "warn",
// 'jsdoc/imports-as-dependencies': 'off',
// 'jsdoc/informative-docs': 'off',
// 'jsdoc/lines-before-block': 'off',
// 'jsdoc/match-description': 'off',
// 'jsdoc/match-name': 'off',
// 'jsdoc/multiline-blocks': 'warn', // Conflicts with prettier
// 'jsdoc/no-bad-blocks': 'off',
// 'jsdoc/no-blank-block-descriptions': 'off',
// 'jsdoc/no-blank-blocks': 'off',
"jsdoc/no-defaults": "warn",
// 'jsdoc/no-missing-syntax': 'off',
"jsdoc/no-multi-asterisks": "warn",
// 'jsdoc/no-restricted-syntax': 'off',
// 'jsdoc/no-types': 'off',
// 'jsdoc/no-undefined-types': 'off',
// 'jsdoc/require-asterisk-prefix': 'off',
// 'jsdoc/require-description': 'off',
// 'jsdoc/require-description-complete-sentence': 'off',
// 'jsdoc/require-example': 'off',
// 'jsdoc/require-file-overview': 'off',
// 'jsdoc/require-hyphen-before-param-description': 'off',
"jsdoc/require-jsdoc": "warn",
"jsdoc/require-param": "warn",
"jsdoc/require-param-description": "warn",
"jsdoc/require-param-name": "warn",
"jsdoc/require-param-type": "warn",
"jsdoc/require-property": "warn",
"jsdoc/require-property-description": "warn",
"jsdoc/require-property-name": "warn",
"jsdoc/require-property-type": "warn",
"jsdoc/require-returns": "warn",
"jsdoc/require-returns-check": "warn",
"jsdoc/require-returns-description": "warn",
"jsdoc/require-returns-type": "warn",
// 'jsdoc/require-template': 'off',
// 'jsdoc/require-throws': 'off',
"jsdoc/require-yields": "warn",
"jsdoc/require-yields-check": "warn",
// 'jsdoc/sort-tags': 'off',
// 'jsdoc/tag-lines': 'warn',
// 'jsdoc/tag-lines': 'off',
// 'jsdoc/text-escaping': 'off',
"jsdoc/valid-types": "warn",
...rules
}
},
{
name: "jsdoc-typescript",
files: typescriptFiles,
rules: {
// https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.1/src/index.js#L216-L242
"jsdoc/check-tag-names": ["warn", { typed: true }],
"jsdoc/no-types": "warn",
// 'jsdoc/no-undefined-types': 'off',
"jsdoc/require-param-type": "off",
"jsdoc/require-property-type": "off",
"jsdoc/require-returns-type": "off",
...typescriptRules
}
}
];
}
function jsonc(options = {}) {
const { files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC], rules = {} } = options;
return [
{
name: "other/jsonc",
files,
languageOptions: {
parser: parserJsonc
},
plugins: {
jsonc: pluginJsonc,
"package-json": pluginPackageJson
},
rules: {
// https://github.com/ota-meshi/eslint-plugin-jsonc/blob/v2.18.1/lib/configs/base.ts
strict: "off",
"no-unused-expressions": "off",
"no-unused-vars": "off",
// https://github.com/ota-meshi/eslint-plugin-jsonc/blob/v2.18.1/lib/configs/recommended-with-jsonc.ts
"jsonc/no-bigint-literals": "error",
"jsonc/no-binary-expression": "error",
"jsonc/no-binary-numeric-literals": "error",
"jsonc/no-dupe-keys": "error",
"jsonc/no-escape-sequence-in-identifier": "error",
// 'jsonc/no-floating-decimal': 'error',
"jsonc/no-hexadecimal-numeric-literals": "error",
"jsonc/no-infinity": "error",
"jsonc/no-multi-str": "error",
"jsonc/no-nan": "error",
"jsonc/no-number-props": "error",
"jsonc/no-numeric-separators": "error",
"jsonc/no-octal-numeric-literals": "error",
"jsonc/no-octal": "error",
"jsonc/no-parenthesized": "error",
"jsonc/no-plus-sign": "error",
"jsonc/no-regexp-literals": "error",
"jsonc/no-sparse-arrays": "error",
"jsonc/no-template-literals": "error",
"jsonc/no-undefined-value": "error",
"jsonc/no-unicode-codepoint-escapes": "error",
"jsonc/no-useless-escape": "error",
// 'jsonc/quote-props': 'error',
// 'jsonc/quotes': 'error',
// 'jsonc/space-unary-ops': 'error',
"jsonc/valid-json-number": "error",
"jsonc/vue-custom-block/no-parsing-error": "error",
// https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/blob/v0.19.0/src/configs/recommended.ts
"package-json/order-properties": "error",
"package-json/repository-shorthand": "error",
"package-json/sort-collections": "error",
"package-json/unique-dependencies": "error",
"package-json/valid-local-dependency": "error",
"package-json/valid-name": "error",
"package-json/valid-package-definition": "error",
"package-json/valid-repository-directory": "error",
"package-json/valid-version": "error",
...rules
}
}
];
}
function markdown(options = {}) {
const {
markdownFiles = [GLOB_MARKDOWN],
markdownInnerFiles = [GLOB_MARKDOWN_SCRIPT, GLOB_MARKDOWN_VUE],
rules = {}
} = options;
return [
{
name: "other/markdown",
files: markdownFiles,
plugins: {
markdown: pluginMarkdown
},
processor: "markdown/markdown"
},
{
name: "other/markdown/code-blocks",
files: markdownInnerFiles,
rules: {
// https://github.com/eslint/markdown/blob/v5.1.0/lib/index.js
"no-console": "off",
"no-redeclare": "off",
"no-undef": "off",
"no-unused-vars": "off",
"@typescript-eslint/consistent-type-imports": "off",
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-vars": "off",
"import/no-unresolved": "off",
"n/no-extraneous-import": "off",
"n/no-extraneous-require": "off",
"n/no-unpublished-bin": "off",
"n/no-unpublished-import": "off",
"n/no-unpublished-require": "off",
"unicorn/prefer-module": "off",
"unused-imports/no-unused-imports": "off",
"unused-imports/no-unused-vars": "off",
"vue/no-unused-emit-declarations": "off",
...rules
}
}
];
}
function next(options = {}) {
const {
files = [GLOB_JSX, GLOB_TSX],
rules = {},
typescriptFiles = [GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "frameworks/next",
files,
plugins: {
"@next/next": pluginNext
},
rules: {
// https://nextjs.org/docs/messages/google-font-display
"@next/next/google-font-display": "warn",
// https://nextjs.org/docs/messages/google-font-preconnect
"@next/next/google-font-preconnect": "warn",
// https://nextjs.org/docs/messages/inline-script-id
"@next/next/inline-script-id": "error",
// https://nextjs.org/docs/messages/next-script-for-ga
"@next/next/next-script-for-ga": "warn",
// Handled by ESLint globals.
// '@next/next/no-assign-module-variable': 'error',
// https://nextjs.org/docs/messages/no-async-client-component
"@next/next/no-async-client-component": "warn",
// https://nextjs.org/docs/messages/no-before-interactive-script-outside-document
"@next/next/no-before-interactive-script-outside-document": "warn",
// https://nextjs.org/docs/messages/no-css-tags
"@next/next/no-css-tags": "warn",
// https://nextjs.org/docs/messages/no-document-import-in-page
"@next/next/no-document-import-in-page": "error",
// https://nextjs.org/docs/messages/no-duplicate-head
"@next/next/no-duplicate-head": "error",
// https://nextjs.org/docs/messages/no-head-element
"@next/next/no-head-element": "warn",
// https://nextjs.org/docs/messages/no-head-import-in-document
"@next/next/no-head-import-in-document": "error",
// https://nextjs.org/docs/messages/no-html-link-for-pages
"@next/next/no-html-link-for-pages": "error",
// https://nextjs.org/docs/messages/no-img-element
"@next/next/no-img-element": "warn",
// https://nextjs.org/docs/messages/no-page-custom-font
"@next/next/no-page-custom-font": "warn",
// https://nextjs.org/docs/messages/no-script-component-in-head
"@next/next/no-script-component-in-head": "error",
// https://nextjs.org/docs/messages/no-styled-jsx-in-document
"@next/next/no-styled-jsx-in-document": "warn",
// https://nextjs.org/docs/messages/no-sync-scripts
"@next/next/no-sync-scripts": "error",
// https://nextjs.org/docs/messages/no-title-in-document-head
"@next/next/no-title-in-document-head": "warn",
"@next/next/no-typos": "warn",
// https://nextjs.org/docs/messages/no-unwanted-polyfillio
"@next/next/no-unwanted-polyfillio": "error",
...rules
}
},
{
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
function node(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/node",
files,
plugins: {
n: pluginN
},
rules: {
// https://github.com/eslint-community/eslint-plugin-n/blob/v17.15.1/lib/configs/_commons.js
"n/no-deprecated-api": "error",
"n/no-extraneous-import": "error",
"n/no-extraneous-require": "error",
"n/no-exports-assign": "error",
// 'n/no-missing-import': 'error', // Handled by eslint-plugin-import-x.
// 'n/no-missing-require': 'error', // Handled by eslint-plugin-import-x.
"n/no-process-exit": "error",
"n/no-unpublished-bin": "error",
"n/no-unpublished-import": "error",
"n/no-unpublished-require": "error",
// 'n/no-unsupported-features/es-builtins': 'error',
// 'n/no-unsupported-features/es-syntax': 'error',
// 'n/no-unsupported-features/node-builtins': 'error',
"n/process-exit-as-throw": "error",
// 'n/hashbang': 'error', // Allow source code to use hashbang for building.
...rules
}
},
{
name: "base/node/typescript",
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
const nuxt3Rules = {
"nuxt/prefer-import-meta": "error"
};
const nuxt2Rules = {
// https://github.com/nuxt/eslint-plugin-nuxt/blob/v4.0.0/lib/configs/base.js
"nuxt/no-env-in-context": "error",
"nuxt/no-env-in-hooks": "error",
"nuxt/no-globals-in-created": "error",
"nuxt/no-this-in-fetch-data": "error",
"nuxt/no-cjs-in-config": "error",
// https://github.com/nuxt/eslint-plugin-nuxt/blob/v4.0.0/lib/configs/recommended.js
"nuxt/no-timing-in-fetch-data": "error"
};
function nuxt(options = {}) {
const { files = [GLOB_VUE], rules = {}, typescriptRules = {} } = options;
return [
{
name: "frameworks/nuxt",
files,
plugins: {
nuxt: hasNuxt3 ? pluginNuxt3 : pluginNuxt2
},
rules: {
...hasNuxt3 ? nuxt3Rules : nuxt2Rules,
...rules,
...hasTypeScript ? typescriptRules : {}
}
},
hasNuxt3 ? {
name: "nuxt-config",
files: ["**/nuxt.config.?([cm])[jt]s?(x)"],
rules: {
"nuxt/nuxt-config-keys-order": "error"
}
} : {}
];
}
function promise(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/promise",
files,
plugins: {
promise: pluginPromise
},
rules: {
// https://github.com/eslint-community/eslint-plugin-promise/blob/v7.2.1/index.js
"promise/always-return": "error",
// 'promise/avoid-new': 'off',
"promise/catch-or-return": "error",
"promise/no-callback-in-promise": "warn",
"promise/no-multiple-resolved": "warn",
// 'promise/no-native': 'off',
"promise/no-nesting": "warn",
"promise/no-new-statics": "error",
"promise/no-promise-in-callback": "warn",
"promise/no-return-in-finally": "warn",
"promise/no-return-wrap": "error",
"promise/param-names": "error",
"promise/prefer-await-to-callbacks": "warn",
"promise/prefer-await-to-then": "warn",
"promise/spec-only": "warn",
"promise/valid-params": "warn",
...rules
}
},
{
name: "base/promise/typescript",
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
function perfectionist(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/perfectionist",
files,
plugins: {
perfectionist: pluginPerfectionist
},
rules: {
// https://perfectionist.dev/rules/sort-array-includes
"perfectionist/sort-array-includes": "error",
// https://perfectionist.dev/rules/sort-classes
"perfectionist/sort-classes": "error",
// https://perfectionist.dev/rules/sort-decorators
"perfectionist/sort-decorators": "error",
// https://perfectionist.dev/rules/sort-enums
"perfectionist/sort-enums": "error",
// https://perfectionist.dev/rules/sort-exports
"perfectionist/sort-exports": "error",
// https://perfectionist.dev/rules/sort-heritage-clauses
"perfectionist/sort-heritage-clauses": "error",
// https://perfectionist.dev/rules/sort-imports
"import/order": "off",
"perfectionist/sort-imports": [
"error",
{
internalPattern: ["^~{1,2}/.*", "^@{1,2}/.*"],
newlinesBetween: "ignore",
groups: [
"builtin",
"external",
"internal",
"parent",
"sibling",
"side-effect",
"side-effect-style",
"index",
"object",
"style",
"external-type",
"builtin-type",
"internal-type",
"parent-type",
"sibling-type",
"index-type",
"unknown"
]
}
],
// https://perfectionist.dev/rules/sort-interfaces
"@typescript-eslint/adjacent-overload-signatures": "off",
"perfectionist/sort-interfaces": "error",
// https://perfectionist.dev/rules/sort-intersection-types
// deprecated
// "@typescript-eslint/sort-type-constituents": "off",
"perfectionist/sort-intersection-types": [
"error",
{
groups: [
"conditional",
"function",
"import",
"intersection",
"keyword",
"literal",
"named",
"object",
"operator",
"tuple",
"union",
"nullish",
"unknown"
]
}
],
// https://perfectionist.dev/rules/sort-jsx-props
"perfectionist/sort-jsx-props": [
"error",
{
groups: ["reserved", "unknown", "callback"],
customGroups: {
reserved: ["children", "dangerouslySetInnerHTML", "key", "ref"],
callback: "on*"
}
}
],
// https://perfectionist.dev/rules/sort-maps
"perfectionist/sort-maps": "error",
// https://perfectionist.dev/rules/sort-modules
"perfectionist/sort-modules": "error",
// https://perfectionist.dev/rules/sort-named-exports
"perfectionist/sort-named-exports": "error",
// https://perfectionist.dev/rules/sort-named-imports
"perfectionist/sort-named-imports": "error",
// https://perfectionist.dev/rules/sort-object-types
// '@typescript-eslint/adjacent-overload-signatures': 'off',
"perfectionist/sort-object-types": "error",
// https://perfectionist.dev/rules/sort-objects
"sort-keys": "off",
"perfectionist/sort-objects": [
"error",
{
groups: ["top", "unknown", "method"],
customGroups: {
top: ["name", "key", "id", "queryKey", "queryFn"]
}
}
],
// https://perfectionist.dev/rules/sort-sets
"perfectionist/sort-sets": "error",
// https://perfectionist.dev/rules/sort-switch-case
"perfectionist/sort-switch-case": "error",
// https://perfectionist.dev/rules/sort-union-types
// deprecated
// '@typescript-eslint/sort-type-constituents': 'off',
"perfectionist/sort-union-types": [
"error",
{
groups: [
"conditional",
"function",
"import",
"intersection",
"keyword",
"literal",
"named",
"object",
"operator",
"tuple",
"union",
"nullish",
"unknown"
]
}
],
// https://perfectionist.dev/rules/sort-variable-declarations
"perfectionist/sort-variable-declarations": "error",
...rules
},
settings: {
perfectionist: {
type: "natural",
order: "asc",
ignoreCase: true,
ignorePattern: [],
specialCharacters: "keep",
locales: "en-US",
partitionByComment: true,
partitionByNewLine: true
}
}
},
{
name: "base/perfectionist/typescript",
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
function react(options = {}) {
const {
files = [GLOB_JSX, GLOB_TSX],
rules = {},
parserOptions = {},
languageOptions = {},
typescriptFiles = [GLOB_TSX],
typescriptRules = {},
typescriptParserOptions = {},
typescriptLanguageOptions = {},
typeCheck = true,
settings = {}
} = options;
return [
{
name: "frameworks/react",
files,
languageOptions: {
parser: parserBabel,
parserOptions: {
babelOptions: {
babelrc: false,
configFile: false,
presets: ["@babel/preset-env", "@babel/preset-react"]
},
ecmaFeatures: {
globalReturn: false,
jsx: true
},
ecmaVersion: "latest",
requireConfigFile: false,
sourceType: "module",
...parserOptions
},
...languageOptions
},
plugins: {
"react-x": pluginReactX,
"react-dom": pluginReactDom,
"react-web-api": pluginReactWebApi,
"react-hooks-extra": pluginReactHooksExtra,
"react-naming-convention": pluginReactNamingConvention,
"react-hooks": pluginReactHooks,
"react-perf": pluginReactPerf,
"react-refresh": pluginReactRefresh
},
rules: {
// https://github.com/Rel1cx/eslint-react/blob/v1.23.2/packages/plugins/eslint-plugin-react-x/README.md
"react-x/ensure-forward-ref-using-ref": "warn",
"react-x/no-access-state-in-setstate": "error",
"react-x/no-array-index-key": "warn",
"react-x/no-children-count": "warn",
"react-x/no-children-for-each": "warn",
"react-x/no-children-map": "warn",
"react-x/no-children-only": "warn",
"react-x/no-children-to-array": "warn",
"react-x/no-clone-element": "warn",
"react-x/no-comment-textnodes": "warn",
"react-x/no-component-will-mount": "error",
"react-x/no-component-will-receive-props": "error",
"react-x/no-component-will-update": "error",
"react-x/no-context-provider": "warn",
"react-x/no-create-ref": "error",
"react-x/no-default-props": "error",
"react-x/no-direct-mutation-state": "error",
"react-x/no-duplicate-jsx-props": "warn",
"react-x/no-duplicate-key": "error",
"react-x/no-forward-ref": "warn",
"react-x/no-implicit-key": "warn",
"react-x/no-missing-key": "error",
"react-x/no-nested-components": "error",
"react-x/no-prop-types": "error",
"react-x/no-redundant-should-component-update": "error",
"react-x/no-set-state-in-component-did-mount": "warn",
"react-x/no-set-state-in-component-did-update": "warn",
"react-x/no-set-state-in-component-will-update": "warn",
"react-x/no-string-refs": "error",
"react-x/no-unsafe-component-will-mount": "warn",
"react-x/no-unsafe-component-will-receive-props": "warn",
"react-x/no-unsafe-component-will-update": "warn",
"react-x/no-unstable-context-value": "warn",
"react-x/no-unstable-default-props": "warn",
"react-x/no-unused-class-component-members": "warn",
"react-x/no-unused-state": "warn",
"react-x/use-jsx-vars": "warn",
// https://github.com/Rel1cx/eslint-react/blob/v1.23.2/packages/plugins/eslint-plugin-react-dom/README.md
"react-dom/no-dangerously-set-innerhtml-with-children": "error",
"react-dom/no-dangerously-set-innerhtml": "warn",
"react-dom/no-find-dom-node": "error",
"react-dom/no-missing-button-type": "warn",
"react-dom/no-missing-iframe-sandbox": "warn",
"react-dom/no-namespace": "error",
"react-dom/no-render-return-value": "error",
"react-dom/no-script-url": "warn",
"react-dom/no-unknown-property": "warn",
"react-dom/no-unsafe-iframe-sandbox": "warn",
"react-dom/no-unsafe-target-blank": "warn",
"react-dom/no-void-elements-with-children": "warn",
// https://github.com/Rel1cx/eslint-react/blob/v1.23.2/packages/plugins/eslint-plugin-react-web-api/README.md
"react-web-api/no-leaked-event-listener": "warn",
"react-web-api/no-leaked-interval": "warn",
"react-web-api/no-leaked-resize-observer": "warn",
"react-web-api/no-leaked-timeout": "warn",
// https://github.com/Rel1cx/eslint-react/blob/v1.23.2/packages/plugins/eslint-plugin-react-hooks-extra/README.md
"react-hooks-extra/no-direct-set-state-in-use-effect": "warn",
"react-hooks-extra/no-useless-custom-hooks": "warn",
"react-hooks-extra/prefer-use-state-lazy-initialization": "warn",
// https://github.com/Rel1cx/eslint-react/blob/v1.23.2/packages/plugins/eslint-plugin-react-naming-convention/README.md
"react-naming-convention/filename-extension": ["warn", "as-needed"],
"react-naming-convention/use-state": "warn",
// https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
// eslint-plugin-react-hooks v5.1.0
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
// https://github.com/cvazac/eslint-plugin-react-perf/commit/9bfa930661a23218f5460ebd39d35d76ccdb5724
// eslint-plugin-react-perf v3.3.3
"react-perf/jsx-no-new-object-as-prop": "error",
"react-perf/jsx-no-new-array-as-prop": "error",
"react-perf/jsx-no-new-function-as-prop": "error",
// https://github.com/ArnaudBarre/eslint-plugin-react-refresh/tree/v0.4.18
"react-refresh/only-export-components": [
"warn",
{
allowExportNames: [
...hasRemix || hasReactRouter ? ["meta", "links", "headers", "loader", "action"] : [],
...hasNext ? [
"dynamic",
"dynamicParams",
"revalidate",
"fetchCache",
"runtime",
"preferredRegion",
"maxDuration",
"config",
"generateStaticParams",
"metadata",
"generateMetadata",
"viewport",
"generateViewport"
] : []
],
allowConstantExport: hasVite
}
],
...rules
},
settings: {
...settings
}
},
{
name: "frameworks/react/typescript",
files: typescriptFiles,
languageOptions: {
parser: parserTypeScript,
...typeCheck ? {
parserOptions: {
projectService: {
allowDefaultProject: ["*.js", "*.config.*"]
},
...typescriptParserOptions
}
} : {
parserOptions: {
...typescriptParserOptions
}
},
...typescriptLanguageOptions
},
rules: {
"react-x/no-duplicate-jsx-props": "off",
"react-x/use-jsx-vars": "warn",
"react-dom/no-unknown-property": "off",
...typeCheck ? {
"react-x/no-leaked-conditional-rendering": "warn"
} : {},
...typescriptRules
}
}
];
}
function reactNative(options = {}) {
const {
files = [GLOB_JSX, GLOB_TSX],
rules = {},
typescriptFiles = [GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "frameworks/react-native",
files,
plugins: {
"react-native": pluginReactNative
},
rules: {
// https://github.com/Intellicode/eslint-plugin-react-native/blob/v4.1.0/index.js
"react-native/no-unused-styles": "error",
"react-native/split-platform-components": "error",
"react-native/no-inline-styles": "error",
"react-native/no-color-literals": "error",
"react-native/no-raw-text": "error",
"react-native/no-single-element-style-arrays": "error",
...rules
}
},
{
name: "react-native-typescript",
files: typescriptFiles,
rules: {
...typescriptRules
}
}
];
}
function regexp(options = {}) {
const {
files = [GLOB_SCRIPT, GLOB_VUE],
rules = {},
typescriptFiles = hasTypeScript && hasVue ? [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE] : [GLOB_DTS, GLOB_TS, GLOB_TSX],
typescriptRules = {}
} = options;
return [
{
name: "base/regexp",
files,
plugins: {
regexp: pluginRegexp
},
rules: {
// https://github.com/ota-meshi/eslint-plugin-regexp/blob/v2.7.0/lib/configs/rules/recommended.ts
"no-control-regex": "error",
"no-misleading-character-class": "error",
"no-regex-spaces": "error",
"prefer-regex-literals": "error",
"no-invalid-regexp": "off",
"no-useless-backreference": "off",
"no-empty-character-class": "off",
"regexp/confusing-quantifier": "warn",
"regexp/control-character-escape": "error",
"regexp/match-any": "error",
"regexp/negation": "error",
"regexp/no-contradiction-with-assertion": "error",
"regexp/no-dupe-characters-character-class": "error",
"regexp/no-dupe-disjunctions": "error",
"regexp/no-empty-alternative": "warn",
"regexp/no-empty-capturing-group": "error",
"regexp/no-empty-character-class": "error",
"regexp/no-empty-group": "error",
"regexp/no-empty-lookarounds-assertion": "error",
"regexp/no-empty-string-literal": "error",
"regexp/no-escape-backspace": "error",
"regexp/no-extra-lookaround-assertions": "error",
"regexp/no-invalid-regexp": "error",
"regexp/no-invisible-character": "error",
"regexp/no-lazy-ends": "warn",
"regexp/no-legacy-features": "error",
"regexp/no-misleading-capturing-group": "error",
"regexp/no-misleading-unicode-character": "error",
"regexp/no-missing-g-flag": "error",
"regexp/no-non-standard-flag": "error",
"regexp/no-obscure-range": "error",
"regexp/no-optional-assertion": "error",
"regexp/no-potentially-useless-backreference": "warn",
"regexp/no-super-linear-backtracking": "error",
"regexp/no-trivially-nested-assertion": "error",
"regexp/no-trivially-nested-quantifier": "error",
"regexp/no-unused-capturing-group": "error",
"regexp/no-useless-assertions": "error",
"regexp/no-useless-backreference": "error",
"regexp/no-useless-character-class": "error",
"regexp/no-useless-dollar-replacements": "error",
"regexp/no-useless-escape": "error",
"regexp/no-useless-flag": "warn",
"regexp/no-useless-lazy": "error",
"regexp/no-useless-non-capturing-group": "error",
"regexp/no-useless-quantifier": "error",
"regexp/no-useless-range": "error",
"regexp/no-useless-set-operand": "error",
"regexp/no-useless-string-literal": "error",
"regexp/no-useless-two-nums-quantifier": "error",
"regexp/no-zero-quantifier": "error",
"regexp/optimal-lookaround-quantifier": "warn",
"regexp/optimal-quantifier-concatenation": "error",
"regexp/prefer-character-class": "error",
"regexp/prefer-d": "error",
"regexp/prefer-plus-quantifier": "error",
"regexp/prefer-predefined-assertion": "error",
"regexp/prefer-question-quantifier": "error",
"regexp/prefer-range": "error",
"regexp/prefer-set-operation": "error",
"regexp/prefer-star-quantifier": "error",
"regexp/prefer-unicode-codepo