mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-03-14 04:41:49 +08:00
404 lines
13 KiB
JavaScript
404 lines
13 KiB
JavaScript
const OFF = 0;
|
||
const WARNING = 1;
|
||
const ERROR = 2;
|
||
|
||
// Prevent importing lodash, usually for browser bundle size reasons
|
||
const LodashImportPatterns = ["lodash", "lodash.**", "lodash/**"];
|
||
|
||
module.exports = {
|
||
root: true,
|
||
env: {
|
||
browser: true,
|
||
commonjs: true,
|
||
node: true,
|
||
},
|
||
parser: "@typescript-eslint/parser",
|
||
parserOptions: {},
|
||
globals: {
|
||
JSX: true,
|
||
},
|
||
extends: [
|
||
"eslint:recommended",
|
||
"plugin:react-hooks/recommended",
|
||
"airbnb",
|
||
"plugin:@typescript-eslint/recommended",
|
||
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||
// 'plugin:@typescript-eslint/strict',
|
||
"plugin:regexp/recommended",
|
||
"prettier",
|
||
"plugin:@docusaurus/all",
|
||
],
|
||
settings: {
|
||
"import/resolver": {
|
||
node: {
|
||
extensions: [".js", ".jsx", ".ts", ".tsx"],
|
||
},
|
||
},
|
||
},
|
||
reportUnusedDisableDirectives: true,
|
||
plugins: ["react-hooks", "@typescript-eslint", "regexp", "@docusaurus"],
|
||
rules: {
|
||
"react/jsx-uses-react": OFF, // JSX runtime: automatic
|
||
"react/react-in-jsx-scope": OFF, // JSX runtime: automatic
|
||
"array-callback-return": WARNING,
|
||
camelcase: WARNING,
|
||
"class-methods-use-this": OFF, // It's a way of allowing private variables.
|
||
curly: [WARNING, "all"],
|
||
"global-require": WARNING,
|
||
"lines-between-class-members": OFF,
|
||
"max-classes-per-file": OFF,
|
||
"max-len": [
|
||
WARNING,
|
||
{
|
||
code: Infinity, // Code width is already enforced by Prettier
|
||
tabWidth: 2,
|
||
comments: 80,
|
||
ignoreUrls: true,
|
||
ignorePattern: "(eslint-disable|@)",
|
||
},
|
||
],
|
||
"arrow-body-style": OFF,
|
||
"no-await-in-loop": OFF,
|
||
"no-case-declarations": WARNING,
|
||
"no-console": OFF,
|
||
"no-constant-binary-expression": ERROR,
|
||
"no-continue": OFF,
|
||
"no-control-regex": WARNING,
|
||
"no-else-return": OFF,
|
||
"no-empty": [WARNING, { allowEmptyCatch: true }],
|
||
"no-lonely-if": WARNING,
|
||
"no-nested-ternary": WARNING,
|
||
"no-param-reassign": [WARNING, { props: false }],
|
||
"no-prototype-builtins": WARNING,
|
||
"no-restricted-exports": OFF,
|
||
"no-restricted-properties": [
|
||
ERROR,
|
||
.../** @type {[string, string][]} */ ([
|
||
// TODO: TS doesn't make Boolean a narrowing function yet,
|
||
// so filter(Boolean) is problematic type-wise
|
||
// ['compact', 'Array#filter(Boolean)'],
|
||
["concat", "Array#concat"],
|
||
["drop", "Array#slice(n)"],
|
||
["dropRight", "Array#slice(0, -n)"],
|
||
["fill", "Array#fill"],
|
||
["filter", "Array#filter"],
|
||
["find", "Array#find"],
|
||
["findIndex", "Array#findIndex"],
|
||
["first", "foo[0]"],
|
||
["flatten", "Array#flat"],
|
||
["flattenDeep", "Array#flat(Infinity)"],
|
||
["flatMap", "Array#flatMap"],
|
||
["fromPairs", "Object.fromEntries"],
|
||
["head", "foo[0]"],
|
||
["indexOf", "Array#indexOf"],
|
||
["initial", "Array#slice(0, -1)"],
|
||
["join", "Array#join"],
|
||
// Unfortunately there's no great alternative to _.last yet
|
||
// Candidates: foo.slice(-1)[0]; foo[foo.length - 1]
|
||
// Array#at is ES2022; could replace _.nth as well
|
||
// ['last'],
|
||
["map", "Array#map"],
|
||
["reduce", "Array#reduce"],
|
||
["reverse", "Array#reverse"],
|
||
["slice", "Array#slice"],
|
||
["take", "Array#slice(0, n)"],
|
||
["takeRight", "Array#slice(-n)"],
|
||
["tail", "Array#slice(1)"],
|
||
]).map(([property, alternative]) => ({
|
||
object: "_",
|
||
property,
|
||
message: `Use ${alternative} instead.`,
|
||
})),
|
||
...[
|
||
"readdirSync",
|
||
"readFileSync",
|
||
"statSync",
|
||
"lstatSync",
|
||
"existsSync",
|
||
"pathExistsSync",
|
||
"realpathSync",
|
||
"mkdirSync",
|
||
"mkdirpSync",
|
||
"mkdirsSync",
|
||
"writeFileSync",
|
||
"writeJsonSync",
|
||
"outputFileSync",
|
||
"outputJsonSync",
|
||
"moveSync",
|
||
"copySync",
|
||
"copyFileSync",
|
||
"ensureFileSync",
|
||
"ensureDirSync",
|
||
"ensureLinkSync",
|
||
"ensureSymlinkSync",
|
||
"unlinkSync",
|
||
"removeSync",
|
||
"emptyDirSync",
|
||
].map((property) => ({
|
||
object: "fs",
|
||
property,
|
||
message: "Do not use sync fs methods.",
|
||
})),
|
||
],
|
||
"no-restricted-syntax": [
|
||
WARNING,
|
||
// Copied from airbnb, removed for...of statement, added export all
|
||
{
|
||
selector: "ForInStatement",
|
||
message:
|
||
"for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.",
|
||
},
|
||
{
|
||
selector: "LabeledStatement",
|
||
message:
|
||
"Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.",
|
||
},
|
||
{
|
||
selector: "WithStatement",
|
||
message:
|
||
"`with` is disallowed in strict mode because it makes code impossible to predict and optimize.",
|
||
},
|
||
{
|
||
selector: "ExportAllDeclaration",
|
||
message:
|
||
"Export all does't work well if imported in ESM due to how they are transpiled, and they can also lead to unexpected exposure of internal methods.",
|
||
},
|
||
// TODO make an internal plugin to ensure this
|
||
// {
|
||
// selector:
|
||
// @ 'ExportDefaultDeclaration > Identifier, ExportNamedDeclaration[source=null] > ExportSpecifier',
|
||
// message: 'Export in one statement'
|
||
// },
|
||
...["path", "fs-extra", "webpack", "lodash"].map((m) => ({
|
||
selector: `ImportDeclaration[importKind=value]:has(Literal[value=${m}]) > ImportSpecifier[importKind=value]`,
|
||
message:
|
||
"Default-import this, both for readability and interoperability with ESM",
|
||
})),
|
||
],
|
||
"no-template-curly-in-string": WARNING,
|
||
"no-unused-expressions": [
|
||
WARNING,
|
||
{ allowTaggedTemplates: true, allowShortCircuit: true },
|
||
],
|
||
"no-useless-escape": WARNING,
|
||
"no-void": [ERROR, { allowAsStatement: true }],
|
||
"prefer-destructuring": WARNING,
|
||
"prefer-named-capture-group": WARNING,
|
||
"prefer-template": WARNING,
|
||
yoda: WARNING,
|
||
|
||
"import/extensions": OFF,
|
||
// This rule doesn't yet support resolving .js imports when the actual file
|
||
// is .ts. Plus it's not all that useful when our code is fully TS-covered.
|
||
"import/no-unresolved": [
|
||
OFF,
|
||
{
|
||
// Ignore certain webpack aliases because they can't be resolved
|
||
ignore: [
|
||
"^@theme",
|
||
"^@docusaurus",
|
||
"^@generated",
|
||
"^@site",
|
||
"^@testing-utils",
|
||
],
|
||
},
|
||
],
|
||
"import/order": [
|
||
WARNING,
|
||
{
|
||
groups: [
|
||
"builtin",
|
||
"external",
|
||
"internal",
|
||
["parent", "sibling", "index"],
|
||
"type",
|
||
],
|
||
"newlines-between": "always",
|
||
pathGroups: [
|
||
// always put css import to the last, ref:
|
||
// https://github.com/import-js/eslint-plugin-import/issues/1239
|
||
{
|
||
pattern: "*.+(css|sass|less|scss|pcss|styl)",
|
||
group: "unknown",
|
||
patternOptions: { matchBase: true },
|
||
position: "after",
|
||
},
|
||
{ pattern: "react", group: "builtin", position: "before" },
|
||
{ pattern: "react-dom", group: "builtin", position: "before" },
|
||
{ pattern: "react-dom/**", group: "builtin", position: "before" },
|
||
{ pattern: "stream", group: "builtin", position: "before" },
|
||
{ pattern: "fs-extra", group: "builtin" },
|
||
{ pattern: "lodash", group: "external", position: "before" },
|
||
{ pattern: "clsx", group: "external", position: "before" },
|
||
// 'Bit weird to not use the `import/internal-regex` option, but this
|
||
// way, we can make `import type { Props } from "@theme/*"` appear
|
||
// before `import styles from "styles.module.css"`, which is what we
|
||
// always did. This should be removable once we stop using ambient
|
||
// module declarations for theme aliases.
|
||
{ pattern: "@theme/**", group: "internal" },
|
||
{ pattern: "@site/**", group: "internal" },
|
||
{ pattern: "@theme-init/**", group: "internal" },
|
||
{ pattern: "@theme-original/**", group: "internal" },
|
||
{ pattern: "@/components/**", group: "internal" },
|
||
{ pattern: "@/libs/**", group: "internal" },
|
||
{ pattern: "@/types/**", group: "type" },
|
||
],
|
||
pathGroupsExcludedImportTypes: [],
|
||
// example: let `import './nprogress.css';` after importing others
|
||
// in `packages/docusaurus-theme-classic/src/nprogress.ts`
|
||
// see more: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#warnonunassignedimports-truefalse
|
||
warnOnUnassignedImports: true,
|
||
},
|
||
],
|
||
"import/prefer-default-export": OFF,
|
||
|
||
"jsx-a11y/click-events-have-key-events": WARNING,
|
||
"jsx-a11y/no-noninteractive-element-interactions": WARNING,
|
||
"jsx-a11y/html-has-lang": OFF,
|
||
|
||
"react-hooks/rules-of-hooks": ERROR,
|
||
"react-hooks/exhaustive-deps": ERROR,
|
||
|
||
// Sometimes we do need the props as a whole, e.g. when spreading
|
||
"react/destructuring-assignment": OFF,
|
||
"react/function-component-definition": [
|
||
WARNING,
|
||
{
|
||
namedComponents: "function-declaration",
|
||
unnamedComponents: "arrow-function",
|
||
},
|
||
],
|
||
"react/jsx-filename-extension": OFF,
|
||
"react/jsx-key": [ERROR, { checkFragmentShorthand: true }],
|
||
"react/jsx-no-useless-fragment": [ERROR, { allowExpressions: true }],
|
||
"react/jsx-props-no-spreading": OFF,
|
||
"react/no-array-index-key": OFF, // We build a static site, and nearly all components don't change.
|
||
"react/no-unstable-nested-components": [WARNING, { allowAsProps: true }],
|
||
"react/prefer-stateless-function": WARNING,
|
||
"react/prop-types": OFF,
|
||
"react/require-default-props": [
|
||
ERROR,
|
||
{ ignoreFunctionalComponents: true },
|
||
],
|
||
|
||
"@typescript-eslint/consistent-type-definitions": OFF,
|
||
"@typescript-eslint/require-await": OFF,
|
||
|
||
"@typescript-eslint/ban-ts-comment": [
|
||
ERROR,
|
||
{ "ts-expect-error": "allow-with-description" },
|
||
],
|
||
"@typescript-eslint/consistent-indexed-object-style": OFF,
|
||
"@typescript-eslint/consistent-type-imports": [
|
||
WARNING,
|
||
{ disallowTypeAnnotations: false },
|
||
],
|
||
"@typescript-eslint/explicit-module-boundary-types": WARNING,
|
||
"@typescript-eslint/method-signature-style": ERROR,
|
||
"@typescript-eslint/no-empty-function": OFF,
|
||
"@typescript-eslint/no-empty-interface": [
|
||
ERROR,
|
||
{
|
||
allowSingleExtends: true,
|
||
},
|
||
],
|
||
"@typescript-eslint/no-inferrable-types": OFF,
|
||
"@typescript-eslint/no-namespace": [WARNING, { allowDeclarations: true }],
|
||
"no-use-before-define": OFF,
|
||
"@typescript-eslint/no-use-before-define": [
|
||
ERROR,
|
||
{ functions: false, classes: false, variables: true },
|
||
],
|
||
"@typescript-eslint/no-non-null-assertion": OFF,
|
||
"no-redeclare": OFF,
|
||
"@typescript-eslint/no-redeclare": ERROR,
|
||
"no-shadow": OFF,
|
||
"@typescript-eslint/no-shadow": ERROR,
|
||
"no-unused-vars": OFF,
|
||
// We don't provide any escape hatches for this rule. Rest siblings and
|
||
// function placeholder params are always ignored, and any other unused
|
||
// locals must be justified with a disable comment.
|
||
"@typescript-eslint/no-unused-vars": [ERROR, { ignoreRestSiblings: true }],
|
||
"@typescript-eslint/prefer-optional-chain": ERROR,
|
||
"@docusaurus/no-html-links": ERROR,
|
||
"@docusaurus/prefer-docusaurus-heading": ERROR,
|
||
"@docusaurus/no-untranslated-text": [
|
||
WARNING,
|
||
{
|
||
ignoredStrings: [
|
||
"·",
|
||
"-",
|
||
"—",
|
||
"×",
|
||
"", // zwj: ​
|
||
"@",
|
||
"WebContainers",
|
||
"Twitter",
|
||
"GitHub",
|
||
"Dev.to",
|
||
"1.x",
|
||
],
|
||
},
|
||
],
|
||
},
|
||
overrides: [
|
||
{
|
||
files: ["packages/*/src/theme/**/*.{js,ts,tsx}"],
|
||
excludedFiles: "*.test.{js,ts,tsx}",
|
||
rules: {
|
||
"no-restricted-imports": [
|
||
"error",
|
||
{
|
||
patterns: LodashImportPatterns.concat(
|
||
// Prevents relative imports between React theme components
|
||
[
|
||
"../**",
|
||
"./**",
|
||
// Allows relative styles module import with consistent filename
|
||
"!./styles.module.css",
|
||
// Allows relative tailwind css import with consistent filename
|
||
"!./styles.css",
|
||
]
|
||
),
|
||
},
|
||
],
|
||
},
|
||
},
|
||
{
|
||
files: ["packages/*/src/theme/**/*.{js,ts,tsx}"],
|
||
rules: {
|
||
"import/no-named-export": ERROR,
|
||
},
|
||
},
|
||
{
|
||
files: ["*.d.ts"],
|
||
rules: {
|
||
"import/no-duplicates": OFF,
|
||
},
|
||
},
|
||
{
|
||
files: ["*.{ts,tsx}"],
|
||
rules: {
|
||
"no-undef": OFF,
|
||
"import/no-import-module-exports": OFF,
|
||
},
|
||
},
|
||
{
|
||
files: ["*.{js,mjs,cjs}"],
|
||
rules: {
|
||
// Make JS code directly runnable in Node.
|
||
"@typescript-eslint/no-var-requires": OFF,
|
||
"@typescript-eslint/explicit-module-boundary-types": OFF,
|
||
},
|
||
},
|
||
{
|
||
// Internal files where extraneous deps don't matter much at long as
|
||
// they run
|
||
files: ["website/**"],
|
||
rules: {
|
||
"import/no-extraneous-dependencies": OFF,
|
||
},
|
||
},
|
||
],
|
||
};
|