diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index f5a9cb43b9..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,17 +0,0 @@ -snapshot* -dist/ -esm/ -lib/ -cjs/ -lib/ -es/ -node_modules/ -static -cypress -script/test/cypress -_site -temp* -static/ -packages/common -packages/ai-core -site/engineering/static diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index df6451340a..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,159 +0,0 @@ -module.exports = { - extends: [ - 'airbnb-base', - 'plugin:react/recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', - ], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'react-hooks', 'simple-import-sort', 'prettier'], - env: { - browser: true, - node: true, - jest: true, - }, - settings: { - react: { - pragma: 'React', - version: 'detect', - }, - }, - parserOptions: { - ecmaVersion: 2019, - sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, - }, - rules: { - 'no-console': [ - 'warn', - { - allow: ['info', 'warn', 'error'], - }, - ], - - // code style config - 'no-param-reassign': 'off', - 'guard-for-in': 'off', - 'no-use-before-define': 'off', - 'no-throw-literal': 'off', - 'no-unused-expressions': 'off', - 'no-bitwise': 'off', - 'no-useless-return': 'off', - 'no-plusplus': [ - 'error', - { - allowForLoopAfterthoughts: true, - }, - ], - 'no-continue': 'off', - 'no-return-assign': 'off', - 'no-restricted-syntax': 'off', - 'no-restricted-globals': 'off', - 'no-unneeded-ternary': 'off', - 'eol-last': 'error', - 'func-names': 'off', - 'consistent-return': 'off', - 'default-case': 'off', - 'no-restricted-imports': [ - 'error', - { - paths: [ - { - name: 'lodash', - message: 'Please use lodash-es instead.', - }, - ], - }, - ], - 'max-len': 'off', - 'no-shadow': 'off', - 'prettier/prettier': [ - 'error', - { - printWidth: 120, - tabWidth: 2, - useTabs: false, - semi: true, - singleQuote: true, - quoteProps: 'as-needed', - jsxSingleQuote: false, - trailingComma: 'all', - bracketSpacing: true, - jsxBracketSameLine: false, - arrowParens: 'always', - proseWrap: 'preserve', - htmlWhitespaceSensitivity: 'css', - endOfLine: 'lf', - }, - ], - // import config - 'import/order': 'off', - 'import/extensions': 'off', - 'import/no-named-as-default': 'off', - 'import/prefer-default-export': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/no-cycle': 'off', - 'import/no-unresolved': 'off', - 'import/no-relative-packages': 'off', - 'simple-import-sort/imports': [ - 'error', - { - groups: [ - // NodeJS 内置模块 - [ - '^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib)(/.*|$)', - ], - // 副作用导入(例如 "dotenv/config" - ['^\\u0000'], - // 第三方包 - ['^react', '^\\w', '^@\\w'], - // 内部路径别名 - ['^@/'], - // 相对路径 - ['^\\.'], - // 类型 - ['^react\\u0000$', '^@?\\w.*\\u0000$', '^@/.*\\u0000$', '^\\..*\\u0000$'], - // css - ['\\.css$', '\\.less$'], - ], - }, - ], - 'simple-import-sort/exports': 'error', - // typescript config - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/indent': ['off', 2], - '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/camelcase': 'off', - '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-use-before-define': ['error', { functions: false }], - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-unused-vars': 'error', - 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], - '@typescript-eslint/consistent-type-imports': [ - 'error', - { - prefer: 'type-imports', - fixStyle: 'separate-type-imports', - disallowTypeAnnotations: false, - }, - ], - // react config - 'react/display-name': 'off', - 'react-hooks/exhaustive-deps': 'warn', - 'react-hooks/rules-of-hooks': 'error', - 'react/prop-types': 'off', - }, - overrides: [ - { - files: ['**/_example/**/*', '**/__tests__/**/*'], - rules: { - 'no-console': 'off', - }, - }, - ], -}; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..114a8e48de --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,89 @@ +import importPlugin from 'eslint-plugin-import'; +import reactHooksPlugin from 'eslint-plugin-react-hooks'; + +import { base, react } from '@rss1102/eslint-config-tdesign'; + +export default [ + ...base, + ...react, + { + ignores: [ + '**/dist/**', + '**/es/**', + '**/esm/**', + '**/lib/**', + '**/cjs/**', + '**/_example-js/**', + '**/node_modules/**', + 'snapshot*/**', + 'static/**', + 'cypress/**', + 'script/test/cypress/**', + '_site/**', + 'temp*/**', + 'packages/common/**', + 'packages/ai-core/**', + 'site/engineering/static/**', + ], + }, + { + files: ['**/*.{js,mjs,cjs,jsx,ts,tsx}'], + plugins: { + import: importPlugin, + 'react-hooks': reactHooksPlugin, + }, + rules: { + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'lodash', + message: 'Please use lodash-es instead.', + }, + ], + }, + ], + '@typescript-eslint/no-unused-vars': 'error', + 'import/first': 'off', + 'no-useless-assignment': 'off', + 'no-unused-vars': 'off', + 'react-hooks/component-hook-factories': 'off', + 'react-hooks/error-boundaries': 'off', + 'react-hooks/exhaustive-deps': 'warn', + 'react-hooks/globals': 'off', + 'react-hooks/immutability': 'off', + 'react-hooks/incompatible-library': 'off', + 'react-hooks/preserve-manual-memoization': 'off', + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/purity': 'off', + 'react-hooks/refs': 'off', + 'react-hooks/set-state-in-render': 'off', + 'react-hooks/set-state-in-effect': 'off', + 'react-hooks/static-components': 'off', + 'react-hooks/unsupported-syntax': 'off', + 'react-hooks/use-memo': 'off', + 'react-hooks/void-use-memo': 'off', + 'simple-import-sort/exports': 'off', + 'simple-import-sort/imports': 'off', + }, + }, + { + files: ['**/_usage/**/*', '**/_example/**/*', '**/__tests__/**/*'], + rules: { + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-unused-vars': 'off', + 'no-unused-vars': 'off', + 'react-hooks/exhaustive-deps': 'off', + 'react-hooks/immutability': 'off', + 'react-hooks/set-state-in-effect': 'off', + 'simple-import-sort/imports': 'off', + }, + }, + { + files: ['**/_example/**/*', '**/__tests__/**/*'], + rules: { + 'no-console': 'off', + }, + }, +]; diff --git a/package.json b/package.json index 974ae074bd..09cc1670e2 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "dev:aigc": "pnpm run build:aigc-jsx-demo && pnpm -C packages/tdesign-react-aigc/site dev", "site:aigc": "pnpm run build:aigc-jsx-demo && pnpm -C packages/tdesign-react-aigc/site build", "site:aigc-preview": "pnpm -C packages/tdesign-react-aigc/site preview", - "lint": "pnpm run lint:tsc && eslint --ext .ts,.tsx ./ --max-warnings 0", - "lint:fix": "eslint --ext .ts,.tsx ./packages/components --ignore-pattern ./packages/components/__tests__ --max-warnings 0 --fix", - "lint:aigc-fix": "eslint --ext .ts,.tsx ./packages/pro-components --ignore-pattern ./packages/pro-components/__tests__ --max-warnings 0 --fix", + "lint": "pnpm run lint:tsc && eslint \"**/*.{ts,tsx}\" --max-warnings 0", + "lint:fix": "eslint \"packages/components/**/*.{ts,tsx}\" --ignore-pattern ./packages/components/__tests__ --max-warnings 0 --fix", + "lint:aigc-fix": "eslint \"packages/pro-components/**/*.{ts,tsx}\" --ignore-pattern ./packages/pro-components/__tests__ --max-warnings 0 --fix", "lint:tsc": "tsc -p ./tsconfig.dev.json ", "generate:usage": "node script/generate-usage/index.js", "generate:coverage-badge": "pnpm run test:coverage && node script/generate-coverage.js", @@ -88,8 +88,8 @@ "@types/react-dom": "^18.2.0", "@types/rimraf": "^4.0.5", "@types/testing-library__jest-dom": "5.14.2", - "@typescript-eslint/eslint-plugin": "^5.13.0", - "@typescript-eslint/parser": "^5.13.0", + "@rss1102/eslint-config-tdesign": "^0.0.2", + "@rss1102/prettier-config-tdesign": "^0.0.1", "@vitejs/plugin-react": "^5.1.1", "@vitest/coverage-istanbul": "^2.1.1", "@vitest/coverage-v8": "^2.1.1", @@ -101,12 +101,8 @@ "cz-conventional-changelog": "^3.3.0", "dom-parser": "^0.1.6", "esbuild": "^0.14.9", - "eslint": "^7.32.0", - "eslint-config-airbnb-base": "^14.2.1", - "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-react": "~7.28.0", - "eslint-plugin-react-hooks": "^4.0.0", - "eslint-plugin-simple-import-sort": "^13.0.0", + "eslint": "^10.5.0", + "eslint-plugin-import": "^2.32.0", "fs-extra": "^11.3.0", "glob": "^9.0.3", "husky": "^7.0.4", diff --git a/packages/common b/packages/common index ae7ab1eebe..81f6f2fdb2 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit ae7ab1eebedb06af7291de3c575deed0a2bcebcf +Subproject commit 81f6f2fdb2b649a437b87bd0d15dc0543fe445c2 diff --git a/packages/components/_util/parseTNode.ts b/packages/components/_util/parseTNode.ts index 18b04d580f..02f8a77c47 100644 --- a/packages/components/_util/parseTNode.ts +++ b/packages/components/_util/parseTNode.ts @@ -34,7 +34,7 @@ export function parseContentTNode(tnode: TNode, props: T) { if (!tnode || ['string', 'number', 'boolean'].includes(typeof tnode)) return tnode as ReactNode; try { return React.cloneElement(tnode as ReactElement, { ...props }); - } catch (e) { + } catch { log.warn('parseContentTNode', `${tnode} is not a valid ReactNode`); return null; } diff --git a/packages/components/_util/react-render.ts b/packages/components/_util/react-render.ts index 6a1e9669ea..6f8c436cf1 100644 --- a/packages/components/_util/react-render.ts +++ b/packages/components/_util/react-render.ts @@ -25,7 +25,7 @@ try { if (mainVersion >= 18 && mainVersion < 19) { legacyCreateRoot = fullClone.createRoot; } -} catch (e) { +} catch { // Do nothing; } diff --git a/packages/components/descriptions/_example/layout.tsx b/packages/components/descriptions/_example/layout.tsx index bae9b5c202..484d15ea6f 100644 --- a/packages/components/descriptions/_example/layout.tsx +++ b/packages/components/descriptions/_example/layout.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Col, Descriptions, Radio, Row, Space } from 'tdesign-react'; -type Layout = 'horizontal' | 'vertical'; +type LayoutType = 'horizontal' | 'vertical'; export default function Layout() { - const [layout, setLayout] = React.useState('horizontal'); - const [itemLayout, setItemLayout] = React.useState('horizontal'); + const [layout, setLayout] = React.useState('horizontal'); + const [itemLayout, setItemLayout] = React.useState('horizontal'); const items = [ { @@ -39,7 +39,7 @@ export default function Layout() { setLayout(val)} + onChange={(val: LayoutType) => setLayout(val)} options={layoutOptions} /> diff --git a/packages/components/form/hooks/useWatch.ts b/packages/components/form/hooks/useWatch.ts index 0367da74a8..c6948b740f 100644 --- a/packages/components/form/hooks/useWatch.ts +++ b/packages/components/form/hooks/useWatch.ts @@ -16,7 +16,8 @@ export default function useWatch(name: NamePath, form: InternalFormInstance) { useEffect(() => { if (!isValidForm) return; - const { registerWatch = noop } = form.getInternalHooks?.(HOOK_MARK); + const internalHooks = form.getInternalHooks?.(HOOK_MARK); + const { registerWatch = noop } = internalHooks || {}; const cancelRegister = registerWatch(() => { const allFieldsValue = form.getFieldsValue?.(true); diff --git a/packages/components/message/Message.tsx b/packages/components/message/Message.tsx index d32ea30e18..84d6df1441 100644 --- a/packages/components/message/Message.tsx +++ b/packages/components/message/Message.tsx @@ -29,7 +29,7 @@ import type { TdMessageProps, } from './type'; -export interface MessagePlugin { +export interface MessagePluginType { (theme: MessageThemeList, message: TNode | MessageOptions, duration?: number): Promise; info: MessageInfoMethod; success: MessageSuccessMethod; @@ -248,7 +248,7 @@ const messageMethod: MessageMethod = (theme: MessageThemeList, content, duration return Promise.resolve(renderElement(theme, getMessageConfig(config))); }; -export const MessagePlugin: MessagePlugin = (theme, message, duration) => messageMethod(theme, message, duration); +export const MessagePlugin: MessagePluginType = (theme, message, duration) => messageMethod(theme, message, duration); MessagePlugin.info = (content, duration) => messageMethod('info', content, duration); MessagePlugin.error = (content, duration) => messageMethod('error', content, duration); MessagePlugin.warning = (content, duration) => messageMethod('warning', content, duration); diff --git a/packages/components/popup/Popup.tsx b/packages/components/popup/Popup.tsx index 4c00cbf5d8..b6c91dd1c8 100644 --- a/packages/components/popup/Popup.tsx +++ b/packages/components/popup/Popup.tsx @@ -369,7 +369,7 @@ const Popup = forwardRef((originalProps, ref onVisibleChange(false, { trigger: 'document' }); } } - } catch (e) { + } catch { // 直接尝试更新 popper.update(); } diff --git a/packages/components/table/hooks/useDragSort.ts b/packages/components/table/hooks/useDragSort.ts index 508fb71406..a84539bc25 100644 --- a/packages/components/table/hooks/useDragSort.ts +++ b/packages/components/table/hooks/useDragSort.ts @@ -329,7 +329,7 @@ function useDragSort(props: TdEnhancedTableProps, options: DragSortOptions) { handle: `.${tableDraggableClasses.handle}`, }); } - } catch (error) { + } catch { // } updateLastRowList(); diff --git a/packages/components/tree/TreeItem.tsx b/packages/components/tree/TreeItem.tsx index f115906697..36fe99e69d 100644 --- a/packages/components/tree/TreeItem.tsx +++ b/packages/components/tree/TreeItem.tsx @@ -311,7 +311,7 @@ const TreeItem = forwardRef( try { // ie throw error firefox-need-it evt.dataTransfer?.setData('text/plain', ''); - } catch (e) { + } catch { // empty } }; diff --git a/prettier.config.mjs b/prettier.config.mjs new file mode 100644 index 0000000000..974977ec3d --- /dev/null +++ b/prettier.config.mjs @@ -0,0 +1 @@ +export { default } from '@rss1102/prettier-config-tdesign';