How to customize HTML formatting with Vue 3 and Prettier? - eslint

I have setup a new Vue 3 project with Eslint and Prettier config.
But when reformatting the HelloWorld.vue I see something ugly like this
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
rel="noopener"
target="_blank"
>babel</a
>
I want something more compact and still readable like this:
<a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" rel="noopener"
target="_blank">babel</a>
I searched for a while and also tried out things like "htmlWhitespaceSensitivity": "ignore" but nothing helps.
.eslintrs.js
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'#vue/typescript/recommended',
'#vue/prettier',
'#vue/prettier/#typescript-eslint',
],
parserOptions: {
ecmaVersion: 2020,
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? ['error', {allow: ['warn', 'error']}] : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
env: {
mocha: true,
},
},
],
}
.prettierrc
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"bracketSpacing": false,
"printWidth": 120,
"jsxBracketSameLine": true,
"htmlWhitespaceSensitivity": "ignore"
}
My Solution
That I wouldn't name an answer, because it doesn't solve the problem with Prettier.
I don't use Prettier any more.
This is my current .eslintrc.js:
module.exports = {
root: true,
env: {
node: true,
},
extends: ['plugin:vue/vue3-essential', '#vue/standard', '#vue/typescript/recommended'],
parserOptions: {
ecmaVersion: 2020,
},
rules: {
'comma-dangle': ['error', 'always-multiline'],
'no-console': process.env.NODE_ENV === 'production' ? ['error', { allow: ['warn', 'error'] }] : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'quotes': ['error', 'single'],
'vue/html-quotes': ['error', 'double'],
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
env: {
jest: true,
},
},
],
}
Together with IntelliJ, this configuration leads to code formatting that looks pretty for me...

That formatting is controlled by Prettier's printWidth option. Since you're seeing the wrapping occur even with a printWidth of 120, the problem is likely that the particular line that <a> is on exceeds 120 characters, including surrounding whitespace (as seen in this demo).
Solution 1: Increase printWidth globally
Increase the printWidth value in .prettierrc to cover that line's character length (probably not the best idea, as it defeats the purpose of the option in your entire project).
Solution 2: Disable Prettier for line
Disable all Prettier rules for that particular line in <template>:
<!-- eslint-disable-next-line prettier/prettier -->
babel
Solution 3: Increase printWidth for the component
Use a component-specific printWidth config in <script> that accommodates an acceptable length (currently no way to configure from <template>):
<script>
/* eslint "prettier/prettier": ["warn", { "printWidth": 200 }] */
</script>

Related

How to resolve conflicts between prettier and eslint

I have set up both prettier and eslint in my node.js project. But I am getting huge amounts of conflicts and syntax errors.
I followed dev.to documentation to set up prettier and eslint and make them compatible with each other.
// .eslintrc.js
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
},
extends: ['standard', 'prettier'],
overrides: [],
parserOptions: {
ecmaVersion: 'latest',
},
rules: {
'prettier/prettier': 'error',
quotes: ['error', 'single'],
semi: ['error', 'always'],
},
plugins: ['prettier'],
};
//.prettierrc.js
module.exports = {
trailingComma: 'es5',
tabWidth: 1,
semi: true,
singleQuote: true,
};

How do I disable There should be no space after '{'.eslintobject-curly-spacing in .eslintrc.js

I am using prettier and I initialized my project with firebase init with the eslint option. But when I save my files, the prettier extension adds spacing in the object curly braces like this:
export { basicHTTP } from './http';
which eslint gives me an error: is there anyway to disable this?
This is my .eslintrc.js file that comes with firebase init:
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'google',
],
parser: '#typescript-eslint/parser',
parserOptions: {
project: ['tsconfig.json', 'tsconfig.dev.json'],
tsconfigRootDir: __dirname,
sourceType: 'module',
},
ignorePatterns: [
'/lib/**/*', // Ignore built files.
],
plugins: ['#typescript-eslint', 'import'],
rules: {
quotes: ['error'],
},
};
Modify your rules to look like this:
rules: {
'object-curly-spacing': ['error', 'always'],
'quotes': ['error'],
},
After this change you probably have to fix all js files to use same syntax, but that's just a good practice.
See: https://eslint.org/docs/rules/quotes
You can disable adding space in vscode when formatting code.
Open settings.json and add the following line
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
"javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
This will fix it on both javascript and typescript

ESLint runs prettier twice if config in .eslintrc and .prettierrc

I am trying to solve a problem with battling formatting on save in VSCode.
I do not have prettier installed as a standalone extension. I have eslint installed. I am working with typescript files.
In my editor, I see a warning on trailing commas and when I hit save, I see the trailing comma vanish, then reappear. I realized that I have trailing comma set to "none" in my .eslintrc.js file and set to "always" in my .prettierrc.js file. They are both below.
My have Vetur installed as well, but I think I only have vetur running on save because my vsconfig file specifies this:
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
But prettier is definitely being run twice. Is there some other setting I should be looking for? Or does eslint run prettier once for each set of config it finds.
Here is my eslintrc file:
module.exports = {
root: true,
env: {
node: true,
browser: true
},
extends: [
'plugin:vue/strongly-recommended',
'#vue/airbnb',
'#vue/typescript',
'plugin:prettier/recommended'
],
parserOptions: {
ecmaVersion: 2020,
parser: '#typescript-eslint/parser',
sourceType: 'module'
},
rules: {
'no-console': 'off',
'no-debugger': 'off',
'#typescript-eslint/no-empty-function': 'off',
'#typescript-eslint/no-namespace': 'off',
'#typescript-eslint/no-explicit-any': 'off',
'#typescript-eslint/no-non-null-assertion': 'off',
'#typescript-eslint/no-non-null-asserted-optional-chain': 'off',
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
'vue/no-v-html': 'off',
'prettier/prettier': [
'warn',
{
singleQuote: true,
semi: true,
trailingComma: 'none',
printWidth: 100,
tabWidth: 2,
endOfLine: 'lf',
arrowParens: 'always',
bracketSpacing: true
}
]
},
overrides: [
{
files: ['**/*.test.ts'],
env: {
jest: true
}
}
]
};
and here is my .pretterrc.js file:
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 100,
tabWidth: 2,
endOfLine: 'lf',
arrowParens: 'always',
bracketSpacing: true
};
I know that I could just make the two files consistent and I will get the proper output, but I don't want the formatting to be run twice. Working with typescript files seems to be slow enough as it is without formatting twice all the time.
I think the relevant portions of my settings.json file are:
"eslint.alwaysShowStatus": true,
"eslint.validate": [
"vue",
"html",
"javascript",
"typescript"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[vue]": {
"editor.defaultFormatter": "octref.vetur"
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"editor.formatOnSave": true,
"vetur.experimental.templateInterpolationService": true,
"vetur.format.defaultFormatter.js": "prettier-eslint",
"vetur.format.defaultFormatter.ts": "prettier-tslint",
"vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": "force-expand-multiline"
},
"prettyhtml": {
"printWidth": 100,
"singleQuote": false,
"wrapAttributes": true,
"sortAttributes": true
},
"vetur.grammar.customBlocks": {
"docs": "md",
"i18n": "json"
}
},
Any pointers of which settings to look at would be appreciated.
I believe I have found the answer.
The first round of prettying is done by eslint and it uses the prettier config found in eslintrc.
The second round of prettying is done by vetur on the typescript section of the vue file and it uses the prettier config found in the prettierrc file.
What I did to fix the problem is to tell vetur not to format the typescript code by changing these two lines in the settings.json file for the workspace:
"vetur.format.defaultFormatter.js": "none",
"vetur.format.defaultFormatter.ts": "none",
These were prettier-eslint previously. Once I changed these to none, the typescript portion of the file removed the trailing commas and left them removed. The html template portion of the file was still formatted properly.
I assume this will speed up my file save since vetur can now ignore the typescript portion of the file when saving since it has already been processed by eslint.
You don't need to put the prettier config in the .eslintrc file, as the latest version of ESLint-plugin-prettier will load it from .prettierrc

ESLint rule: Allow whitespace before/after element

I want ESLint to stop removing whitespaces around an element, like this:
I can't seem to find any rule to disable this. I've searched https://eslint.org/docs/rules/ and tried different rules that I thought might solve my problem, but without success. I'm not even 100% sure if it's ESLint or my VS Code settings.
My eslintrc:
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
'plugin:prettier/recommended',
'#vue/prettier'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
and my VS Code user settings:
{
"prettier.eslintIntegration": true,
"prettier.jsxSingleQuote": true,
"vetur.validation.template": false,
"eslint.validate": [
{
"language": "vue",
"autoFix": true
},
{
"language": "html",
"autoFix": true
},
{
"language": "javascript",
"autoFix": true
}
],
"eslint.autoFixOnSave": true,
"editor.formatOnSave": true,
"vetur.completion.useScaffoldSnippets": false,
"diffEditor.ignoreTrimWhitespace": false,
Thank you.
In VSCode you can add .editorconfig file at the root of project and add following code so vscode does not remove whitespace
[*]
trim_trailing_whitespace = false

eslint insists on not indenting <script> tag

I have 'indent': ['warn', 2, { 'SwitchCase' : 1 }] in my eslintrc rules.
However, it complains that the indentation of this code in a Vue template is wrong:
<script>
export default {
name: 'Sausage',
}
</script>
Instead, it wants this:
<script>
export default {
name: 'Sausage',
}
</script>
I find this much uglier and harder to read — and it's inconstent with the <template> and <style> tags in the same template.
How can I tell eslint that the contents of a <script> tag should be indented one level?
In your .eslintrc.js, add a rule for "vue/script-indent" and turn off the "indent" rule for .vue files. There's options to configure indentation for switch statements here as well.
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
"indent": ["error", 4],
"vue/script-indent": ["error", 4, {
"baseIndent": 1,
"switchCase": 1,
"ignores": []
}],
"space-before-function-paren": ["error", "never"],
},
overrides: [
{
"files": ["*.vue"],
"rules": {
"indent": "off"
}
}
],
parserOptions: {
parser: 'babel-eslint'
}
}

Resources