vuejs / vetur

Vue tooling for VS Code.
https://vuejs.github.io/vetur/
MIT License
5.75k stars 593 forks source link

[Feature Request] Pure ESLint support (formatter for TS, JS, and HTML) #2315

Open josh-hemphill opened 4 years ago

josh-hemphill commented 4 years ago

Feature Request

The title sums it up. Creating this to track discussion, comments/progress, and current workarounds/configs that are working for ESLint purists.

josh-hemphill commented 4 years ago

My current config doesn't work for css as far as I can tell. I believe what it's doing is having VSCode tell vetur that it is the formatter for vue files so that I still get code completion and javascript intellisense, but doesn't actually format-on-save, instead, my ESLint is extended to also format .vue files through the ESLint VSCode extension.

// .eslintrc.js
module.exports = {
    extends: ['standard', 'eslint:recommended', 'plugin:vue/recommended'],
    plugins: ['vue'],
    parserOptions: {
        parser: 'babel-eslint',
    },
}

// vscode settings.json
    "[vue]": {
        "editor.defaultFormatter": "octref.vetur",
        "editor.formatOnSave": false
    },
    "[javascript]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
    },
    "[typescript]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
    },
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    "eslint.validate": [
        "vue",
        "javascript",
        "javascriptreact",
        "typescript",
    ],
    "eslint.format.enable": true,
    "vetur.format.enable": false,

// package.json
    "devDependencies": {
        "babel-eslint": "^10.1.0",
        "eslint": "^6.8.0",
        "eslint-loader": "^4.0.2",
        "eslint-plugin-vue": "^6.2.2",
        "vue-eslint-parser": "^7.1.0"
    }
ux-engineer commented 4 years ago

Your settings.json is a bit confusing in that you are setting Vetur as the default vue-file formatter and are not using formatOnSave. But then ESLint is enabled with codeActionsOnSave.

I've tried this. Some quick observations:

  1. Vetur is giving some new linting errors that are not appearing when I'm running this command from CLI: vue-cli-service lint --ext .js,.ts,.vue src/

  2. The Vue CLI bootstrapped HelloWorld started giving linting error on the IDE:

No overload matches this call. The last overload gave the following error. Argument of type '{ name: string; props: { msg: { type: StringConstructor; default: string; }; }; }' is not assignable to parameter of type 'ComponentOptionsWithObjectProps<{ msg: { type: StringConstructor; default: string; }; }, unknown, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, Record<...>, string, Readonly<...>, { ...; }>'. Property '$bvToast' is missing in type '{ name: string; props: { msg: { type: StringConstructor; default: string; }; }; }' but required in type 'ComponentOptionsBase<Readonly<{ msg: string; } & {}>, unknown, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, Record<string, any>, string, { ...; }>'.Vetur(2769)

// Error on the object itself
export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      default: '',
    },
  },
});
  1. Script Setup SFC props and context are not found, even when I have turned off no-undef rule:
<script setup="props, context" lang="ts">

However, I do have a bit different plugins installed which might affect my setup compared to yours:

  "devDependencies": {
    "@babel/plugin-proposal-export-default-from": "^7.10.4",
    "@intlify/eslint-plugin-vue-i18n": "^0.9.0",
    "@typescript-eslint/eslint-plugin": "^4.2.0",
    "@typescript-eslint/parser": "^4.2.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "@vue/eslint-config-airbnb": "^5.0.2",
    "@vue/eslint-config-typescript": "^5.0.2",
    "eslint": "^7.10.0",
    "eslint-plugin-import": "^2.20.2",
    "eslint-plugin-vue": "^7.0.0-0",
    "typescript": "^4.0.3",
  },

.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'plugin:vue/vue3-recommended',
    '@vue/airbnb',
    '@vue/typescript/recommended',
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-undef': 0, // Script Setup SFC support not working correctly yet
    'import/extensions': 0,
    'import/prefer-default-export': 0,
    '@typescript-eslint/ban-ts-ignore': 0,
    '@typescript-eslint/no-empty-function': 0,
  }
};

Here's my .vscode/settings.json with Vetur turned off, however I'd like to integrate Vetur into this setup if possible:

{
  // Note: These settings get applied only when this project's parent folder is opened as the project root.
  // ----------------------------------------
  // FILE EOL CHARACTER
  // Use End of Line characters: \n for LF, and \r\n for CRLF.
  "files.eol": "\n",
  "files.insertFinalNewline": true,
  "files.trimFinalNewlines": true,
  "files.trimTrailingWhitespace": true,
  // ----------------------------------------
  // EDITOR FORMATTER MAPPING
  "editor.defaultFormatter": "dbaeumer.vscode-eslint",
  // ----------------------------------------
  // EDITOR CODE ACTIONS ON SAVE
  "editor.codeActionsOnSave": {
    // "source.fixAll": true,
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  },
  // ----------------------------------------
  // ESLINT FORMATTER
  "eslint.enable": true,
  "eslint.alwaysShowStatus": true,
  "eslint.options": {
    "extensions": [
      ".html",
      ".js",
      ".ts",
      ".vue",
      ".json"
    ]
  },
  "eslint.validate": [
    "javascript",
    "vue",
    "typescript"
  ],
  // ----------------------------------------
  // VETUR FORMATTER
  // Disable rules if user has extension installed and enabled.
  "vetur.validation.template": false,
  "vetur.validation.style": false,
  "vetur.format.defaultFormatter.html": "none",
  "vetur.format.defaultFormatter.css": "none",
  "vetur.format.defaultFormatter.scss": "none",
  "vetur.format.defaultFormatter.js": "none",
  "vetur.format.defaultFormatter.ts": "none",
  // ----------------------------------------
  // STYLELINT FORMATTER
  "stylelint.enable": true,
  // ----------------------------------------
  // SCSS SUPPORT
  "scss.showErrors": true,
  "css.validate": true,
  "scss.validate": true,
  // ----------------------------------------
  // HTML SUPPORT
  "html.format.enable": false,
  "emmet.triggerExpansionOnTab": true,
  "emmet.includeLanguages": {
    "vue-html": "html"
  },
}
johnsoncodehk commented 3 years ago

Some experience sharing:

I try to forward the formatting request to the corresponding language service of the <template>, <style>, <script> region, so as to support pure ESLint or the formatting behavior the user wants.

But the result is that the user experience is very poor... Due to various restrictions, I have to write temporary physical files for the formatting code and open these formats in front of the user to start the formatter.

Therefore, based on user experience, formatting request forwarding is not a feasible approach.