mirror of
https://github.com/nonebot/nonebot2.git
synced 2026-07-25 09:42:52 +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",
|
||||
"prettier": "prettier --config ./.prettierrc --write \"./website/\"",
|
||||
"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: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:fix": "stylelint --fix \"**/*.css\"",
|
||||
"pyright": "pyright"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"@docusaurus/eslint-plugin": "3.10.2",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-regexp": "^1.15.0",
|
||||
"eslint": "^9.39.4",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-regexp": "^3.1.0",
|
||||
"globals": "^17.6.0",
|
||||
"jiti": "^2.7.0",
|
||||
"prettier": "^3.0.3",
|
||||
"pyright": "1.1.393",
|
||||
"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,
|
||||
"noEmitHelpers": true
|
||||
},
|
||||
"include": ["./**/.eslintrc.js", "./**/.stylelintrc.js"],
|
||||
"include": ["eslint.config.ts", "eslint.rules.ts", "./**/.stylelintrc.js"],
|
||||
"exclude": ["node_modules", "**/lib/**/*"]
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.10.2",
|
||||
"@docusaurus/eslint-plugin": "3.10.2",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@nullbot/docusaurus-plugin-changelog": "^3.8.0",
|
||||
"@nullbot/docusaurus-preset-nonepress": "^3.8.0",
|
||||
|
||||
Reference in New Issue
Block a user