React TypeScript: תיקון אוטומטי של eslint למקסימום אורך לא עובד
אני מנסה להגדיר את setup של eslint עבור React TypeScript כך שאורך הקוד המקסימלי יהיה 80, ואם הקוד ארוך מ-80 תווים, השורה תתפצל והקוד יעבור לשורה הבאה אוטומטית. אבל נראה שה-auto-fix של max-length ב-eslint שלי לא עובד. אני מקבל רק אזהרה וכאשר אני לוחץ על quick fix זה פשוט מבטל את כל הקומפוננטה. כרגע, הקוד שלי נראה כך, אני צריך לגלול עד סוף השורה כדי לראות את כל הקודים. תשומת לב: מחקתי את ההרחבה של prettier.
זוהי ההגדרה שלי של .eslintrc.js
module.exports = {
parser: "@typescript-eslint/parser",
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended"
],
parserOptions: {
jsx: true,
useJSXTextNode: true
},
plugins: [
'@typescript-eslint',
"react",
"react-hooks"
],
settings: {
react: {
version: "999.999.999" // no latest option, 999.999.999 as a hack
}
},
rules: {
semi: ["warn", "always"],
indent: "off",
"@typescript-eslint/indent": ["warn", 2],
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/interface-name-prefix": 0,
"@typescript-eslint/no-empty-interface": 0,
"react/jsx-uses-vars": 1,
"quotes": "off",
"@typescript-eslint/quotes": ["warn", "backtick", { avoidEscape: true }],
"max-len": ["warn", { code: 80, ignoreComments: true }],
"arrow-parens": ["warn", "always"],
"arrow-spacing": "warn",
"no-var": "warn",
"no-const-assign": "warn",
"no-dupe-class-members": "warn",
"no-duplicate-imports": ["warn", { includeExports: true }],
"prefer-arrow-callback": ["warn", { "allowNamedFunctions": true }],
"prefer-const": "warn",
"react/display-name": ["warn", { "ignoreTranspilerName": true }],
"padding-line-between-statements": [
"warn",
{ blankLine: "always", prev: "function", next: "function" }
],
"prefer-destructuring": [
"warn",
{
array: false,
object: true
},
{
enforceForRenamedProperties: false
}
],
"template-curly-spacing": "warn",
"no-dupe-args": "warn",
"no-dupe-keys": "warn",
"no-duplicate-case": "warn",
"no-empty": "warn",
"no-extra-semi": "warn",
"no-extra-parens": ["warn", "all"],
"no-extra-boolean-cast": "warn",
"no-func-assign": "warn",
"no-inner-declarations": "warn",
"no-irregular-whitespace": "warn",
"no-sparse-arrays": "warn",
"no-unreachable": "warn",
"accessor-pairs": "warn",
"block-scoped-var": "warn",
curly: "warn",
"default-case": "warn",
"dot-notation": "warn",
eqeqeq: "warn",
"guard-for-in": "warn",
"no-empty-pattern": "warn",
"no-multi-spaces": ["warn", { ignoreEOLComments: true }],
"no-new": "warn",
"no-new-func": "warn",
"array-bracket-newline": ["warn", { multiline: true }],
"array-bracket-spacing": ["warn", "never"],
"block-spacing": "warn",
"brace-style": ["warn", "1tbs", { allowSingleLine: true }],
camelcase: "warn",
"comma-dangle": [
"warn",
{
arrays: "never",
objects: "never",
imports: "never",
exports: "never",
functions: "never"
}
],
"comma-spacing": ["warn", { before: false, after: true }],
"comma-style": ["warn", "last"],
"computed-property-spacing": ["warn", "never"],
"eol-last": ["warn", "always"],
"func-call-spacing": ["warn", "never"],
"func-names": ["warn", "always", { "generators": "as-needed" }],
"func-style": ["warn", "expression", { allowArrowFunctions: true }],
"jsx-quotes": ["warn", "prefer-double"],
"key-spacing": ["warn", { beforeColon: false }],
"keyword-spacing": ["warn", { before: true }],
"lines-around-comment": ["warn", { beforeBlockComment: false }],
"no-array-constructor": "warn",
"no-lonely-if": "warn",
"no-multiple-empty-lines": ["warn", { max: 1, maxEOF: 1 }],
"no-multi-assign": "warn",
"no-trailing-spaces": "warn",
"no-unneeded-ternary": "warn",
"no-whitespace-before-property": "warn",
"object-curly-spacing": ["warn", "always"],
"object-property-newline": ["warn", { allowAllPropertiesOnSameLine: true }],
"padded-blocks": ["warn", "never"],
"quote-props": ["warn", "always"],
"semi-spacing": ["warn", { before: false, after: true }],
"semi-style": ["warn", "last"],
"sort-vars": ["warn", { ignoreCase: true }],
"space-before-blocks": ["warn", "always"],
"space-before-function-paren": ["warn", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
"space-in-parens": ["warn", "never"],
"spaced-comment": ["warn", "always"],
"switch-colon-spacing": "warn",
"@typescript-eslint/explicit-member-accessibility": "warn",
"no-empty-function": "off",
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
};
** זהו הקובץ שלי .vscode/settings.json **
{
"editor.cursorBlinking": "blink",
"editor.cursorStyle": "line",
"editor.detectIndentation": false,
"editor.fontFamily": "'Operator Mono', 'SF Mono', Menlo, Operator Mono, Monaco, 'Courier New', monospace",
"editor.fontLigatures": true,
"editor.fontSize": 14,
"editor.fontWeight": "500",
"editor.insertSpaces": true,
"editor.letterSpacing": 0,
"editor.lineHeight": 28,
"editor.lineNumbers": "on",
"editor.minimap.enabled": true,
"editor.quickSuggestions": {
"comments": false,
"other": true,
"strings": false
},
"editor.quickSuggestionsDelay": 10,
"editor.renderControlCharacters": true,
"editor.renderIndentGuides": true,
"editor.renderWhitespace": "all",
"editor.rulers": [
90,
100
],
"editor.snippetSuggestions": "top",
"editor.tabCompletion": "on",
"editor.tabSize": 2,
"editor.trimAutoWhitespace": true,
"files.autoGuessEncoding": true,
"files.autoSave": "onFocusChange",
"files.defaultLanguage": "html",
"files.exclude": {
"**/*.pyc": true,
"**/package-lock.json": true,
"**/styles/css/": true,
"**/.DS_Store": true,
"**/.git": true,
"**/.hg": true,
"**/.svn": true,
"**/CVS": true,
"**/distribution/": true,
"**/dist/": true,
"**/libraries/": true,
"**/lib/": true,
"**/node_modules/": true,
"**/build/": true,
},
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"window.zoomLevel": 0,
"workbench.iconTheme": "vs-seti",
"workbench.sideBar.location": "left",
"editor.dragAndDrop": false,
"extensions.ignoreRecommendations": true,
"files.associations": {
"*.vue": "html",
"Vagrantfile": "ruby",
"*.js": "javascript"
},
"python.linting.pylintEnabled": false,
"python.linting.lintOnSave": false,
"python.linting.pycodestyleEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length=100",
],
"python.linting.pycodestyleArgs": [
"--ignore=E501"
],
"[plaintext]": {},
"[javascript]": {
"editor.formatOnSave": true,
},
"[typescriptreact]": {
"editor.formatOnSave": true,
},
"[typescript]": {
"editor.formatOnSave": true
},
"javascript.updateImportsOnFileMove.enabled": "never",
"breadcrumbs.enabled": true,
"[python]": {
"editor.tabSize": 4,
},
"typescript.validate.enable": false,
"javascript.validate.enable": false,
"docthis.includeDescriptionTag": true,
"docthis.inferTypesFromNames": true,
"merge-conflict.autoNavigateNextConflict.enabled": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"explorer.confirmDelete": false,
"typescript.surveys.enabled": false,
"eslint.validate": [
{ "language": "javascript", "autoFix": true },
{ "language": "javascriptreact", "autoFix": true },
{ "language": "typescript", "autoFix": true },
{ "language": "typescriptreact", "autoFix": true }
],
"eslint.alwaysShowStatus": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"workbench.colorTheme": "Night Owl",
"workbench.statusBar.visible": true,
"eslint.codeAction.disableRuleComment": {},
"eslint.codeAction.showDocumentation": {}
}
תשובה #1
היו כמה בעיות שפתוחות, על הוספת תיקון אוטומטי לכלל max-len, אבל למרבה הצער, נראה שצוות eslint אינו מעוניין לקדם את זה (הסיבות מצוינות בדיון).
אתה יכול לשקול לבטל את הכלל הזה עבור השורה המסוימת:
// eslint-disable-next-line max-len
אם אתה מחפש פתרון תיקון אוטומטי, אני ממליץ לך להתקין מחדש את Prettier.
תשובה #2
הערה: התשובה למטה לא מתייחסת במדויק לשאלה. השאלה היא על eslint באופן ספציפי, והפתרון הזה הוא עבור prettier, ספריית עיצוב שונה שיכולה לעבוד לצד eslint.
במקרה שלי היה שגיאה בקובץ eslintrc.json שלי (פסיק נוסף בסוף) ולכן לא נבחרה שום הגדרת lint.
תיקון זה פתר את הבעיה שלי.
גם, ודא שאתה משתמש ב-prettier כתלות ולא כהרחבה ב-VScode.
prettier.config.json
module.exports = {
singleQuote: true,
trailingComma: 'all',
arrowParens: 'avoid',
printWidth: 80,
bracketSpacing: true,
jsxBracketSameLine: true,
};
.eslintrc.json
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended",
"airbnb",
"plugin:prettier/recommended"
],
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react",
"react-hooks",
"prettier"
],
"rules": {
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
},
{
"usePrettierrc": true
}
],
"import/no-dynamic-require":"off",
"global-require": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"no-use-before-define": "off",
"react/react-in-jsx-scope": "off",
"import/no-cycle": "off",
"react/prop-types": "off",
"react/jsx-filename-extension": "off",
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"react/jsx-props-no-spreading": "off",
"no-param-reassign": "off",
"radix": "off",
"import/order": "off",
"no-plusplus": "off",
"no-underscore-dangle": "off",
"no-unused-expressions": "off",
"array-callback-return": "warn",
"react/jsx-no-bind": "off",
"class-methods-use-this": "off",
"consistent-return": "off",
"new-cap": "off",
"react/destructuring-assignment": "off",
"react/forbid-prop-types": "off",
"import/prefer-default-export": "off",
"react/no-unused-state": "warn",
"no-unused-vars": "warn",
"no-nested-ternary": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off",
"react/sort-comp": "off",
"jsx-a11y/anchor-is-valid": "off",
"no-return-assign": "warn",
"react/no-array-index-key": "warn",
"guard-for-in": "warn",
"no-restricted-syntax": "warn",
"max-classes-per-file": "off",
"react/state-in-constructor": "off",
"react/static-property-placement": "off",
"react/prefer-stateless-function": "off",
"react/no-did-update-set-state": "warn",
"camelcase": "off",
"prefer-destructuring": "warn",
"no-await-in-loop": "warn",
"no-restricted-globals": "off",
"no-bitwise": "off",
"eqeqeq": "warn",
"no-shadow": "warn",
"jsx-a11y/label-has-associated-control": "off",
"react/button-has-type": "off"
}
}
package.json
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^7.22.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"node-sass": "^4.14.1",
"prettier": "^2.2.1"
}
