Airbnb, ESLint, Prettier conflict over Switch and Case indentation - configuration

I am setting up my React Redux project to use ESLint with Airbnb configs and Prettier. I've been modifying certain things to how I want them, but now I've run into a problem with indentations on switch & case statements that I can't seem to fix.
I am editing my project in VSCode. I click on the errors and fix with ESLint, reducing the indent by 4 spaces, but then more errors show up from Prettier, asking to re-indent everything by another 4 spaces.
I want to change the current indentation width. I want it set to 4 spaces when I use tabs. It's not a must, but if it is possible, I would prefer that the case keywords in switch blocks to be indented.
List of packages that pertain to my ESLint configuration:
prettier
eslint
eslint-config-airbnb
eslint-plugin-import
eslint-plugin-jsx-a11y
eslint-plugin-react
eslint-import-resolver-webpack
eslint-config-prettier
eslint-plugin-prettier
Relevant portion of my .eslintrc.json
"extends": ["airbnb", "prettier", "prettier/react"],
"plugins": ["react", "prettier"],
"rules": {
"react/jsx-filename-extension": [
1,
{
"extensions": [".js", "jsx"]
}
],
"prettier/prettier": "error",
"indent": ["error", 4, { "SwitchCase": 1 }],
"react/jsx-indent": ["error", 4],
"react/jsx-indent-props": ["error", 4],
"class-methods-use-this": 0,
"no-else-return": 0,
"no-plusplus": [2, { "allowForLoopAfterthoughts": true }],
"no-param-reassign": 0
}
My .prettierrc config-file:
The setting below is necessary for Prettier to format indentations harmoniously with the rest of the development environments configurations while using ESLint.
"prettier": {
"tabWidth": 4
}
Here is the script I am formatting:
It is a hangman game.
switch (action.type) {
case GUESS_LETTER:
return Object.assign(
{},
state,
state.guessWord.includes(action.guessLetter)
? addCorrectGuess(
state.rightLetters.slice(), // <-- error here!
action.guessLetter, // <-- error here!
state.guessWord // <-- error here!
) // <-- error here!
: addWrongGuess(
state.wrongLetters.slice(), // <-- error here!
action.guessLetter // <-- error here!
) // <-- error here!
);
}
My first attempt to get this working was to add { "SwitchCase": 1 } to the ESLint config file. That reduced the number of errors (which was almost the entire block), but there are still errors. I can't figure out where the conflict is exactly.
[UPDATE] To my eternal shame, I believe I discovered the problem. I simply removed the configuration for intends from the ESLint configuration. I removed this:
"indent": ["error", 4, { "SwitchCase": 1 }],
"react/jsx-indent": ["error", 4],
"react/jsx-indent-props": ["error", 4],
And now it seems to be behaving normally. I assume this is because it screws up Prettier when trying to handle indents. I only needed the configuration for Prettier.
Lesson: test more by removing configurations which may be causing conflict before posting.

To make sure this is marked as solved:
I simply removed the configuration for indents from the ESLint configuration. I removed this:
"indent": ["error", 4, { "SwitchCase": 1 }],
"react/jsx-indent": ["error", 4],
"react/jsx-indent-props": ["error", 4],
And now it seems to be behaving normally. I assume this is because it screws up Prettier when trying to handle indents. I only needed the configuration for Prettier.
Lesson: test more by removing configurations which may be causing conflict before posting.

I had the same problem as mentioned in the question above, however I figured out how to solve it in a way that not only could the "indent" setting be kept, but so it can be adjusted, allowing for tabWidth to be set as you like.
First I want to note, so we're all on the same page, what the set-up I am using for linting/formatting exactly is:
Source Code Editor: V.S. Code
Linting Utility: ESLint
Opinionated Formatter: Prettier
Style-Guide: AirBnB
Additionally I also equip the following, which I download using NPM:
eslint-plugin-prettier
eslint-config-prettier
eslint-config-airbnb
For those familiar with linting while using V.S. Code, you guys know that what I am using is actually the short list. There is all kinds of other configs, plugins & extensions that can be obtained. The important thing to note here, is that I am using a tried & true setup, that allows Prettier, and ESLint to work harmoniously together.
With that said, even having a good configuration, and all the correct extensions I still had a problem with the above rule, the same as the developer who posted the question. I knew the problem had to do with ESLint's rules, and how they were being configured in my .eslintrc.json file. After much research, and near mastering ESLint, I found that I was correct. There are a few ESLint rules, (3 ESLint rules, and 1 Prettier Setting), that you need to have configured properly, however; at the same time you need to make sure your .prettierrc file settings are in-sync with your .eslintrc.json file rules. Once you understand it all, it is actually not as complicated as it sounds.
STEP #1 Know what tabWidth you want and set it in .prettierrc
First off you need to decide what you want your styles tab-width to be. (Most Style-Guides set there tab-width at (2x Space-Width), but many dev's will change there settings to a (4x Space-Width). Any thing other than 2x and 4x is considered taboo.)
Go ahead and open your .prettierrc file (or what ever mimetype of prettier configuration file you use), then set 'tabWidth' to your liking, just make sure that you stick with a consistant tabWidth from here on out, becuase ESLint needs to be in sync with prettier.
Your '.prettierrc' file should look similar to this:
{
"printWidth": 90,
"tabWidth": 4,
"useTabs": false,
"trailingComma": "all",
"singleQuote": true,
"semi": true,
"bracketSpacing": false,
}
STEP #2: set the "max-len" rule in .eslintrc.json**
open up your .eslintrc.json file (or whatever version of ESLint configuration file mime-type that you use), and set the "max-len" rule in the rules property of your eslintrc.json. The rule is not in the file by default so you will have to write it in. To see how, review the Example I Created Below.
Be sure that the "tabWidth" property within ESLint's "max-len" rule, holds exactly the same value, as the "tabWidth" setting within your .prettierrc file.
There are some other rule options here that are important to set properly as well. The first, 'code', sets the max amount of chars each line can hold, aka(max-line-length). When "code" is set ESlint will not allow more characters than what "code" has been set to. The catch is that you absolutely must Make sure that the "printWidth" setting in your .prettierrc file, which you probably will have to write in, is set to the same value as the "code" property's value in your .eslintrc.json max-len rule.
"ignoreUrls" can be set either way and make sure the rule does throw an error by leaving the word "error" as it is.
Here is an example of my max-len rule in ESLint
"rules": {
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
See the .prettierrc example above, to view how to set "printWidth"
STEP #3: ESLint's "no-tabs" Rule
The "no-tabs" rule, is a 'must set', w/o it your linting & formatting > can unsynchronize.
You can set "allowIndentationTabs" as you like, Allowing for, or disallowing indentation tabs won't make a difference.
What the no-tabs rule should look like:
"rules": {
"no-tabs": ["error", {"allowIndentationTabs": true}],
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
STEP #4: ESLint's "indent" Rule, by far the most important rule of this discussion
Seriously this one is important. Its the one that gets thrown out in an attempt to fix the switch indentation problem, which doesn't give you control over other settings, like setting your own tab-width. The "indent" rule.
First make sure indent is active by setting error to error as you see it, you could also set it to warn, but its better to set it as error so prettier knows to fix it imeadiatly. The next setting is the width of your indentations, which has to be the same exact value as your tabWidth in your .prettierrc file, and as in the "max-len" ESLint rule.
"indent": ["error", 4, {"SwitchCase": 1}],
The last settings in the brackets, "SwitchCase" can be confusing. No one explained any of this to me at first so I had to figure it out on my own, and this screwed me up a bit. The number that "SwitchCase" gets set to is not like the 4 before it. The 4 that comes before it is the initial setting of the "indent" rule and can stand alone like this:
"indent": 4; // throws error
// or
"indent": ["warn", 4] // Throws warning, which is somtimes less annoying than an error
So it is important to note that the value 4 that you see in the "indent" rule, is how many spaces an indent will be. This led me to believe that the 1 after "SwitchCase" meant how many spaces that the switch keyword case will be indented.
Example:
switch (x) {
case 1:
break;
}
That is not how it works though. The number that rule "SwitchCase" is set to, tells the editor how many times to indent the keyword 'case'. So if the "indent" rule is set to 4, and the "SwitchCase" rule is set to 4, then ESLint will expect an indentation of 4x4=16. At the end of the day ESLint will actually expect more than 16, because ESLint is going to take on all the indentation from different levels of blocks that the switch statement is found in, this ends up leading to ESLint expecting 24-36 spaces of indentation, that's crazy.
"SwitchCase" needs to be set to 1.
"rules": {
"indent": ["error", 4, {"SwitchCase": 1}],
"no-tabs": ["error", {"allowIndentationTabs": true}],
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
If you set all the rules right that should work for you
If it is still not working, try starting with a clean slate, delete your .eslintrc.json file, and create a new eslintrc.json file, and build it anew. You shouldn't have to start over with a new .prettierrc file.
To Wrap Up
Prettier wants to indent everything uninformed like. So if tabWidth is set to 4, and tabWidth & indent is set to 4 in ESlint then every block gets indented 4 spaces be prettier, no more and no less.
The whole problem initially is that, the style guides often ask that the keyword case not be indented, so when ESLint is setup, that is what it is configured to do by the NPM config you install upon initializing ESLint. However that does not work with prettier.
This answer wound up much longer than I thought it would. Getting Prettier, ESLint & VS Code to work harmoniously together is a very involved task, especially for first timers. I use Babel on top of this AST stack (I made that term up lol, what else would you call it?). If you want to be able to lint documents that contain TC39 ECMAScript Stage-3 Proposals, this includes features such as Private-Members, Static Methods, ect..., then you will need to use configure ESLint to use Babel's parser.

Related

How do I enable only specific snippets in strings and why is my json snippet not working in json?

Ok, I am new to coding and just found out about costume snippets in VS-Code. I wrote some and they all worked pretty much as expected, but now I have some problems/questions. I have done some research but couldn't find any solutions.
1. how do I enable for example this snippet only in strings? Is there even a way? I don't want all my snippets to work in strings, just some.
"tab": {
"prefix": ["tab"],
"body": [
"${1|\\t,\\t\\t,\\t\\t\\t,\\t\\t\\t\\t,\\t\\t\\t\\t\\t,\\t\\t\\t\\t\\t\\t|}$0"
],
"description": "insert escaped tab"
},
adding this to the settings enables all snippets in strings which i don't want
"editor.quickSuggestions": {
"strings": true
},
2. I have written a snippet that should insert some lines into my launch.json file and it basically works the way I want, but only if I put the snippet in my global snippet file and not set the scope to json. It also does not work if I put it in the json snippet file (json.json). Why?
"launch json": {
// "scope": "json",
"prefix": "launch",
"body": [
"\"version\": \"0.2.0\",",
"\"configurations\": [",
"\t{",
"\t\t\"type\": \"${1|firefox,chrome|}\",",
"\t\t\"reAttach\": false,", // is there a way to auto remove this line if chrome is chosen
"\t\t\"request\": \"launch\",",
"\t\t\"name\": \"Launch index.html\",",
"\t\t\"file\": \"\\${workspaceFolder}/index.html\"",
"\t}",
"],",
"$0",
],
"description": "insert launch json"
},
that's the snippets output
"version": "0.2.0",
"configurations": [
{
"type": "firefox",
"reAttach": false,
"request": "launch",
"name": "Launch index.html",
"file": "${workspaceFolder}/index.html"
}
],
also is there a way to change the inserted lines depending on what option I chose from the list?
it's not really necessary, just wondering (the "reAttach": false, option only exists with firefox, so i don't need the line if i choose one of the other options)
3. Another problem I have is that I copied and then customized some already existing snippets (for java for example) and now it is showing both options in intellisense. I know, I know, I can press F1 -> insert snippet and click the eye symbol behind them to hide them from intellisense but that only works if the snippet actually is in the list, which isn't true for all of them. I just can't find some of them. Where can I find and disable them?
4. One last thing, I tried making a snippet for css with "prefix": ["*","somethingElse"], but i could not use the snippet with the * only the somethingElse worked, why is that? I already made two other snippets that use . and # as prefix and they also worked just fine. Is there something special about * when it comes to snippets?
I have no idea how to fix the main 4 problems or what causes them. But one way I thought about solving the optional line problem was something like this:
"\t\t\"type\": \"${1|firefox,chrome|}\",${2:\n\t\t\"reAttach\": false,}",
that way I can delete the line with one button if I don't need it. But the question was more about if it's possible in general so change some other lines depending on the option chosen from the list.

Disable wavy yellow underline in vs code for HTML

How do I ignore this error. I have used the id attribute for some tags in order to reference them by id in javascript, but it shows this error:
CSS id selector '...' not found.
Please tell me how to ignore or disable this error.
maybe your css is not formatted properly.
try:
<style>
#phone {
your css here;
}
</style>
You need to make sure you mark the code with # to show that it's an id and not a class or something else.
Update: First section of answer no longer valid as of the lastest updates since original post which removed the css.validation option. see
If you are using the HTML CSS Support extension by ecmel, you can go to .vscode/settings.json and add
"css.validation": {
"id": false,
"class": false
}
This will turn off css validation for class name and id.
More information on this at the Visual Studio MarketPlace for this extension under Selector Validation here or the Github repository readme Selector Validation Section
Note:
1) Also don't forget to add a comma after the setting that comes before (as JSON format is comma separated).
Example:
{
"java.codeGeneration.generateComments": true,
"css.styleSheets": [
// (1)
"https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css",
"src/main/resources/static/css/styles.css"
],
"css.validation": {
"id": false,
"class": true
}
}
Sometimes you need to restart / close and reopen vscode after saving changed to the file for them take effect.
There is a way to configure styleSheets. This next bit is taken from their documentation see Additional Styles Section:
Additional Style Sheets
If it is not possible to specify local or remote styles in HTML or via
template inheritance, they can be specified in VS Code settings per
workspace folder in .vscode/settings.json and will suggest for all
HTML files within that workspace folder:
.vscode/settings.json
"css.styleSheets": [
// (1)
"https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css",
// (2)
"/site.css",
// (3)
"site.css",
// (4)
"./site.css"
]

How to prevent VS Code from breaking up long HTML lines into multiple lines?

When my elements with attributes get long, VS Code seems to break the line up into multiple lines:
(I would like three lines here instead of seven, one line per element)
I am using prettier for formatting, and have set the printWidth option which works in javascript code, but for HTML it seems to be overridden by VS Code.
I´ve tried fiddling around with the wrapAttributes and the html.format.wrapLineLength settings, but none of those seem to have any effect.
How to deal with this matter?
UPDATE:
Thanks alot for your answers. I havent been notified by them, so sorry for not taking action.
I´ve tried all of your suggestions, but the problem remains the same.
This is my current config based on your suggestions.
settings.json:
"html.format.wrapLineLength": 0,
"html.format.enable": false,
"html.format.wrapAttributes": "auto",
"vetur.format.defaultFormatterOptions": {
"prettyhtml": {
"printWidth": 300,
"singleQuote": false,
"wrapAttributes": false,
"sortAttributes": false
}
}
.prettierrc.json:
{
"semi": true,
"trailingComma": "none",
"singleQuote": true,
"printWidth": 300,
"tabWidth": 2,
"useTabs": true,
"jsxBracketSameLine": true
}
You can add "html.format.wrapLineLength": 0 in settings.json.
This worked for me...
In your "Settings.json" file add the line
"prettier.printWidth": 300
I'm not sure if it's just the built-in HTML formatting settings but you can give this a try.
If you don't want to enable wrapping for HTML:
"html.format.wrapAttributes": "auto", # wrap only when line length is exceeded
"html.format.wrapLineLength": 0, # disable max chars per line
If you have other HTML formatter extensions, you can simply disable the built-in:
"html.format.enable": false,
If your HTML is still breaking-up with the *.wrap disabled or with html.format.enable false, then it's not the built-in VS code settings that's causing it.
Settings -> Extensions -> HTML:
Format: Wrap Line Length
Maximum amount of characters per line (0 = disable).
0
That worked for me.
Here is what I did. I created .prettierrc.json file inside project folder. And then added below settings to it.
{
"html.format.wrapAttributes": "auto",
"html.format.wrapLineLength": 0,
"printWidth": 1000
}
The printWidth setting is important here. Increase/Decrease it as per your preferences as you can not disable it completely.
This problem was driving me crazy because I hate when my code wraps I feel like it is so much harder to read. I read a ton of stuff and couldn't get my code to stop wrapping. So if you tried everything already mentioned and your code still wraps then you have an extension that is causing it to wrap. So go to File>Preferences>Settings
Then click on your extensions and go through them and find which one is causing them to wrap. In my case I had Vetur(a Vue extension) using Prettier which was causing my code to wrap.
What you could also do and what I do now is install Prettier and set the Print Width on that to the width of your screen so anything longer will break but for the most part it will keep stuff on the same line for you.
check your extension because i think VS code editor default don't have a auto break function. maybe you install a extension that have a auto break line. hope this help
You should check extensions of visual studio code and disable "JS-CSS-HTML Formatter" or any other formatter that is bothering
My situation differed slightly in terms of what was being split onto new lines. When formatting documents with large chunks of HTML it would wrap long paragraphs of text up onto multiple lines and automatically add space/tab indentation.
I added the following into my settings.json:
"html.format.unformattedContentDelimiter": "p, li",
This kept all text within <p> and <li> tags on one line without introducing whitespace characters. You can then use VSCode native text wrapping with alt + z to visually wrap the text without introducing whitespace characters.
In my situation I was using SVG in my html. And whenever I used Ctrl + Shift + I to format my HTML document, it would split the SVGs into multiple lines like this:
<svg id="logo-1" width="132" height="35" viewBox="0 0 132 35" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.51 11.26H41.72V24.26H38.51V11.26ZM43 19.37C43 16.15 45 14.22 48 14.22C51 14.22 53"></path>
<path d="M32.16 12.11C32.1601 10.1197 31.5591 8.17576 30.4357 6.53282C29.3123 4.88988 27.7188 "></path>
<path d="M82.16 12.19C32.1601 10.1197 31.5591 8.17576 30.4357 6.53282C29.3123 4.88988 27.7188 "></path>
</svg>
Whereas I wanted them to be in single line and still format my documents.
My solution:
Select the SVG you want to convert to single line. Then press F1 and type Join Lines and hit enter.
After converting all SVGs into one line, Press F1. Type Open Settings (JSON) and open the settings file and add the following entry at the end:
"html.format.contentUnformatted": "svg"
Now formatting your document should not split your SVGs into multiple lines.
PS: of course, it can be any other html tag.
If you're using VSCode, put this in your .code-workspace file:
"settings": {
"editor.defaultFormatter":"octref.vetur",
"vetur.format.defaultFormatter.html":"prettyhtml",
"vetur.format.defaultFormatterOptions": {
"prettyhtml": {
"printWidth": 500,
}
},
}
After a long try, I made it work while working with Vue.js, this is my config.json
{
"html.format.wrapAttributes": "auto",
"html.format.wrapLineLength": 0,
"prettier.printWidth": 300,
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
},
}
Do not move anything else, lol. Good luck!
I'm a fan of prettier I wouldn't prefer another formatter over prettier,
so the most neat solution I've found is in vscode settings.json
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"html.format.wrapLineLength": 0,
"html.format.wrapAttributes": "auto",
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
}
}
this disables prettier only for html files and uses default vscode html formatter which is in html quite similar to prettier, and using prettier anywhere else, BTW in this case the formatonsave feature is enabled and works for html files as well that's why I like it
this one line can make difference it works for me.. "vetur.format.defaultFormatter.html": "none",

Extending VS Code syntax highlighting

Is there a way to extend Visual Studio Code syntax highlighting for specific items using the user settings (or similar methods not involving writing an extension)?
I am using a color theme but would like to change the syntax colouring for a specific namespace of HTML tags, e.g.
<div></div> uses standard colouring from theme
<ext:div></ext:div> uses a different color
No, there is nothing in VSCode proper (no extensions) that will highlight an arbitrary regex. (Well, there is the Search feature, but the highlighting from that is temporary.)
Short of writing an extension or using an existing one that does this, the most capable method of highlight customization is the textMateRules mechanism of editor.tokenCustomizations in settings.json.
Now, the built-in TextMate grammar simply classifies "ext:div" as unrecognized, so the best possible with this approach is to change the highlighting for all unrecognized tags. That would look like this:
// https://code.visualstudio.com/docs/getstarted/themes
"editor.tokenColorCustomizations": {
"textMateRules": [
{
"scope": [
"meta.tag.other entity.name.tag",
],
"settings": {
"foreground": "#080",
"fontStyle": "bold",
},
},
],
},
Screenshot:
See also this answer that goes through the process of adding textMateRules in a bit more detail.
If you don't find a better, more standard way to do this, the extension TODO Highlight would work for you. It is typically used to highlight special comments for yourself like "FIXME" but could be used in your case with a regex like:
"todohighlight.keywordsPattern": "\\s*<\\s*\\/{0,1}ext:.*\\s*>",
And then you can set the coloring any way you want:
"todohighlight.defaultStyle": {
"color": "red",
// "letterSpacing": "1px",
// "backgroundColor": "rgba(170,102,0,1)",
"backgroundColor": "transparent"
// "borderRadius": "4px",
"isWholeLine": false
},

give a 'toastr' popup its own options

I've got toastr popups all through my app. They may or may not be custom-configured in my app.
I am using Angular, though I'm not sure this is actually Angular-toastr.
I want to make this one toastr have different options (position, sticky, close-button), - even from other toastrs on the same page.
Is there a way to specify options for a single toaster instance, so that others don't inherit its options?
Everywhere in my app, I just call
toastr.success("Go team!");
and it uses whatever defaults are already set.
Here, I want to something like this:
var bigToast = new toastr;
bigToast.options = {
"closeButton": true,
"positionClass": "toast-top-full-width",
"tapToDismiss": true
}
bigToast.success("Yah! REALLY go team!")
That way, only bigToast is affected. 'course it's not a constructor, so it fails.
I'm trying this:
toastr.options = {
"closeButton": true,
"positionClass": "toast-top-full-width",
"tapToDismiss": true
}
toastr.success(":)");
and even that has no effect, so I'm clearly implementing it wrong. I see the :) but none of the options have been picked up.
As far as I can tell, the toastr object is empty. This:
toastr.options.positionClass = "toast-top-center"
throws an error:
TypeError: Cannot set property 'positionClass' of undefined
I am clearly a dunce, since this apparently so simple, virtually no working examples are necessary.
These config forms show what you can do but now how you actually do it.
https://foxandxss.github.io/angular-toastr/
http://codeseven.github.io/toastr/demo.html
You just need to include the options as third argument.
toastr.success(":)","",{
"closeButton": true,
"positionClass": "toast-top-full-width",
"tapToDismiss": true});
The second argument is the title, keep that blank if you don't want to show a title.