mirror of
https://github.com/nonebot/nonebot2.git
synced 2026-07-31 07:24:42 +00:00
🔧 migrate eslint to flat config
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
dist
|
|
||||||
node_modules
|
|
||||||
.yarn
|
|
||||||
.history
|
|
||||||
build
|
|
||||||
lib
|
|
||||||
-403
@@ -1,403 +0,0 @@
|
|||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { defineConfig, globalIgnores } from "eslint/config";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
import globals from "globals";
|
||||||
|
import js from "@eslint/js";
|
||||||
|
import react from "eslint-plugin-react";
|
||||||
|
import reactHooks from "eslint-plugin-react-hooks";
|
||||||
|
import importPlugin from "eslint-plugin-import";
|
||||||
|
// @ts-expect-error: no types provided
|
||||||
|
import jsxA11y from "eslint-plugin-jsx-a11y";
|
||||||
|
import docusaurus from "@docusaurus/eslint-plugin";
|
||||||
|
import regexp from "eslint-plugin-regexp";
|
||||||
|
import prettier from "eslint-config-prettier/flat";
|
||||||
|
|
||||||
|
import rules from "./eslint.rules";
|
||||||
|
|
||||||
|
const plugins = defineConfig([
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
react.configs.flat.recommended,
|
||||||
|
reactHooks.configs.flat.recommended,
|
||||||
|
importPlugin.flatConfigs.recommended,
|
||||||
|
jsxA11y.flatConfigs.recommended,
|
||||||
|
regexp.configs["flat/recommended"],
|
||||||
|
prettier,
|
||||||
|
|
||||||
|
// The published @docusaurus/eslint-plugin doesn't provide a flat config yet
|
||||||
|
// This adapts its legacy "all" config to flat config
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
"@docusaurus": docusaurus,
|
||||||
|
},
|
||||||
|
rules: docusaurus.configs.all.rules,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ignores = globalIgnores([
|
||||||
|
"**/dist/**",
|
||||||
|
"**/lib/**",
|
||||||
|
"**/build/**",
|
||||||
|
"**/.docusaurus/**",
|
||||||
|
"node_modules",
|
||||||
|
".yarn",
|
||||||
|
".history",
|
||||||
|
"coverage",
|
||||||
|
]);
|
||||||
|
|
||||||
|
export default defineConfig(plugins, rules, ignores, {
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2022,
|
||||||
|
sourceType: "module",
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
...globals.commonjs,
|
||||||
|
JSX: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
"import/resolver": {
|
||||||
|
node: {
|
||||||
|
extensions: [".js", ".jsx", ".ts", ".tsx"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
react: {
|
||||||
|
version: "19",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
+392
@@ -0,0 +1,392 @@
|
|||||||
|
import { defineConfig } from "eslint/config";
|
||||||
|
|
||||||
|
const OFF = 0;
|
||||||
|
const WARNING = 1;
|
||||||
|
const ERROR = 2;
|
||||||
|
|
||||||
|
// Prevent importing lodash, usually for browser bundle size reasons
|
||||||
|
const LodashImportPatterns = ["lodash", "lodash.**", "lodash/**"];
|
||||||
|
|
||||||
|
export default defineConfig(
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
"array-callback-return": WARNING,
|
||||||
|
camelcase: WARNING,
|
||||||
|
"class-methods-use-this": OFF, // It's a way of allowing private variables.
|
||||||
|
curly: [WARNING, "all"],
|
||||||
|
"global-require": OFF, // Deprecated, @typescript-eslint/no-require-import is enough
|
||||||
|
"no-alert": 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.",
|
||||||
|
},
|
||||||
|
...["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": OFF,
|
||||||
|
"no-useless-escape": WARNING,
|
||||||
|
"no-void": [ERROR, { allowAsStatement: true }],
|
||||||
|
"prefer-destructuring": OFF,
|
||||||
|
"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,
|
||||||
|
// `import clsx from "clsx"` triggers it since clsx v2 also provides a
|
||||||
|
// named export; renaming the imports would diverge from upstream themes
|
||||||
|
"import/no-named-as-default": OFF,
|
||||||
|
|
||||||
|
"jsx-a11y/click-events-have-key-events": WARNING,
|
||||||
|
"jsx-a11y/no-noninteractive-element-interactions": WARNING,
|
||||||
|
"jsx-a11y/html-has-lang": OFF,
|
||||||
|
|
||||||
|
// 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 },
|
||||||
|
],
|
||||||
|
"react/jsx-uses-react": OFF, // JSX runtime: automatic
|
||||||
|
"react/react-in-jsx-scope": OFF, // JSX runtime: automatic
|
||||||
|
"react-hooks/set-state-in-effect": WARNING, // TODO re-enable later?
|
||||||
|
"react-hooks/rules-of-hooks": ERROR,
|
||||||
|
"react-hooks/exhaustive-deps": ERROR,
|
||||||
|
|
||||||
|
"@typescript-eslint/no-empty-object-type": OFF,
|
||||||
|
"@typescript-eslint/prefer-optional-chain": OFF,
|
||||||
|
"@typescript-eslint/consistent-type-definitions": OFF,
|
||||||
|
"@typescript-eslint/require-await": OFF,
|
||||||
|
"@typescript-eslint/no-explicit-any": WARNING,
|
||||||
|
"@typescript-eslint/no-unused-expressions": [
|
||||||
|
WARNING,
|
||||||
|
{ allowTaggedTemplates: true, allowShortCircuit: true },
|
||||||
|
],
|
||||||
|
|
||||||
|
"@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,
|
||||||
|
argsIgnorePattern: "^_",
|
||||||
|
varsIgnorePattern: "^_",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"@docusaurus/no-html-links": ERROR,
|
||||||
|
"@docusaurus/prefer-docusaurus-heading": ERROR,
|
||||||
|
"@docusaurus/no-untranslated-text": [
|
||||||
|
WARNING,
|
||||||
|
{
|
||||||
|
ignoredStrings: [
|
||||||
|
"·",
|
||||||
|
"-",
|
||||||
|
"—",
|
||||||
|
"×",
|
||||||
|
"", // zwj: ​
|
||||||
|
"@",
|
||||||
|
"WebContainers",
|
||||||
|
"Twitter",
|
||||||
|
"X",
|
||||||
|
"GitHub",
|
||||||
|
"Dev.to",
|
||||||
|
"1.x",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
files: ["packages/*/src/theme/**/*.{js,ts,tsx}"],
|
||||||
|
ignores: ["**/*.test.{js,ts,tsx}", "**/__tests__/**"],
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Website-specific rules
|
||||||
|
{
|
||||||
|
files: ["website/**"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-require-imports": OFF,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
+13
-11
@@ -11,24 +11,26 @@
|
|||||||
"clear": "pnpm --filter nonebot clear",
|
"clear": "pnpm --filter nonebot clear",
|
||||||
"prettier": "prettier --config ./.prettierrc --write \"./website/\"",
|
"prettier": "prettier --config ./.prettierrc --write \"./website/\"",
|
||||||
"lint": "pnpm lint:js && pnpm lint:style",
|
"lint": "pnpm lint:js && pnpm lint:style",
|
||||||
|
"lint:ci": "pnpm lint:js --quiet && pnpm lint:style",
|
||||||
"lint:js": "eslint --cache --report-unused-disable-directives \"**/*.{js,jsx,ts,tsx,mjs}\"",
|
"lint:js": "eslint --cache --report-unused-disable-directives \"**/*.{js,jsx,ts,tsx,mjs}\"",
|
||||||
"lint:js:fix": "eslint --cache --report-unused-disable-directives --fix \"**/*.{js,jsx,ts,tsx,mjs}\"",
|
"lint:js:fix": "pnpm lint:js --fix",
|
||||||
"lint:style": "stylelint \"**/*.css\"",
|
"lint:style": "stylelint \"**/*.css\"",
|
||||||
"lint:style:fix": "stylelint --fix \"**/*.css\"",
|
"lint:style:fix": "stylelint --fix \"**/*.css\"",
|
||||||
"pyright": "pyright"
|
"pyright": "pyright"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@docusaurus/eslint-plugin": "3.10.2",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@eslint/js": "^10.0.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.48.0",
|
"eslint": "^9.39.4",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-config-prettier": "^8.8.0",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react-hooks": "^7.1.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-regexp": "^3.1.0",
|
||||||
"eslint-plugin-regexp": "^1.15.0",
|
"globals": "^17.6.0",
|
||||||
|
"jiti": "^2.7.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"pyright": "1.1.393",
|
"pyright": "1.1.393",
|
||||||
"stylelint": "^15.10.3",
|
"stylelint": "^15.10.3",
|
||||||
|
|||||||
Generated
+287
-313
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -40,6 +40,6 @@
|
|||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"noEmitHelpers": true
|
"noEmitHelpers": true
|
||||||
},
|
},
|
||||||
"include": ["./**/.eslintrc.js", "./**/.stylelintrc.js"],
|
"include": ["eslint.config.ts", "eslint.rules.ts", "./**/.stylelintrc.js"],
|
||||||
"exclude": ["node_modules", "**/lib/**/*"]
|
"exclude": ["node_modules", "**/lib/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.10.2",
|
"@docusaurus/core": "3.10.2",
|
||||||
"@docusaurus/eslint-plugin": "3.10.2",
|
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
"@nullbot/docusaurus-plugin-changelog": "^3.8.0",
|
"@nullbot/docusaurus-plugin-changelog": "^3.8.0",
|
||||||
"@nullbot/docusaurus-preset-nonepress": "^3.8.0",
|
"@nullbot/docusaurus-preset-nonepress": "^3.8.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user