Vscode-icons: Clarify how to override icons for file associations

Created on 17 Nov 2017  路  37Comments  路  Source: vscode-icons/vscode-icons

  • [x] I'm sure this issue is not a _duplicate_.
  • [ ] I want to create an icon request

Either the documentation doesn't make it very clear how to do this, there's something wrong with how I'm trying to do this or this is a limitation that should be documented:

I use React in lots of projects, so I've added "files.associations": {"*.js": "javascriptreact"} to make my life easier. This is intentional. Sadly this results in React icons in my non-React code, which is less than helpful.

I would prefer seeing the JS icon everyhwere by default, so I've tried the following:

{
  "icon": "reactjs",
  "disabled": true
}

This worked, but not as expected: all JS files now showed up with the default icon. So I tried an override:

{
  "icon": "js",
  "extensions": ["js"],
  "languages": ["javascriptreact"],
  "format": "svg",
  "extends": "js",
  "overrides": "reactjs"
}

This doesn't seem to do anything. I then proceeded to remove combinations of random lines from that and to juggle around "reactjs", "js", "javascript" and "javascriptreact" in various permutations but no combination produced any results: upon restart, VSCode still gleefully render blue React icons in every folder tree.

The ideal solution I want to achieve is to have "js" files _never_ show up with the React icon but to keep the file association for *.js to be "javascriptreact" (because that's a clean superset of "javascript") and also have *.jsx files correctly show up with the react icon.

question / debate

Most helpful comment

@pluma, just put this into your User Settings:

 "files.associations": {
    "*.jsx": "javascriptreact"
    , "*.js": "javascriptreact"
  }
  ,"vsicons.associations.files": [
    { "icon": "js", "extensions": ["js"], "format": "svg" }
  ]

That should do it. You will get *.js and *.jsx associated with react but keep the JS logo for the *.js files.

PS: Remember to execute -> F1: Icons: Apply Icons Customization

All 37 comments

What you are trying to achieve contradicts with your settings.
.jsx are javascriptreact and .js are javascript. If you tell vscode that js files are javascriptreact then the React icon is correctly displayed.
You can't set js to javascriptreact and expect to keep the js icon.

I'm trying to have the js icon for javascriptreact files. Ideally I would want to have the js icon for javascriptreact files with the js file extension but keep the reactjs icon for javascriptreact files with the jsx file extension but I'd settle for simply having the js icon for javascriptreact files regardless of extension.

Exactly my point You can't tell vscode that js files are javascriptreact and expect it to show the js icon but keep showing the reactjs icon for jsx. If you override the reactjs icon with js then js AND the jsx files will have the js icon.
Long story short, by assigning javascriptreact to js, js AND jsx will have the reactjs icon. By overriding the icon. both js AND jsx files will have the icon you set.

That's what I'm saying. I'd be okay with settling on having the js icon for javascript_and_ javascriptreact as it doesn't seem to be possible to have different icons based on file extension alone but I can't figure out how to do that either. I'd expect something like this: json { "icon": "js", "format": "svg", "overrides": "reactjs" } to result in javascriptreact files having the js icon but that doesn't seem to work.

Basically, having all files (both jsx and js) use the js icon would be preferrable to the current situation which is having all files use the reactjs icon (because js is associated with javascriptreact). But I can't figure out how to make that happen either.

Is the use of

"files.associations": {
        "*.js": "javascriptreact"
    }

a must?

@pluma, just put this into your User Settings:

 "files.associations": {
    "*.jsx": "javascriptreact"
    , "*.js": "javascriptreact"
  }
  ,"vsicons.associations.files": [
    { "icon": "js", "extensions": ["js"], "format": "svg" }
  ]

That should do it. You will get *.js and *.jsx associated with react but keep the JS logo for the *.js files.

PS: Remember to execute -> F1: Icons: Apply Icons Customization

"vsicons.associations.files": [
        { "icon": "js", "extensions": ["jsx"], "format": "svg", "overrides": "reactjs" }
    ],

does the trick.

@robertohuertasm It doesn't.

If what @pluma wants to achieve is this

image

Then it certainly works the way I proposed. I've tested it. (Both associated to javascriptreact).

The ideal solution I want to achieve is to have "js" files never show up with the React icon but to keep the file association for *.js to be "javascriptreact" (because that's a clean superset of "javascript") and also have *.jsx files correctly show up with the react icon.

@robertohuertasm That's already the default behavior.
What @pluma wants is to associate js to javascriptreact but both js and jsx files to have the js icon.
This is achieved by setting:

"files.associations": {
      "*.js": "javascriptreact"
    },
"vsicons.associations.files": [
      { "icon": "js", "extensions": ["jsx"], "format": "svg", "overrides": "reactjs" },
      { "icon": "js", "extensions": ["js"], "format": "svg" }
    ]

{ "icon": "js", "extensions": ["jsx"], "format": "svg", "overrides": "reactjs" } sets the js icon for jsx files and
{ "icon": "js", "extensions": ["js"], "format": "svg" } overides the js language id.

@JimiC check the quote in my previous comment: and also have *.jsx files correctly show up with the react icon.

@robertohuertasm Ahh, yes you are right. Sorry.
Well, @pluma now you have to choose which one you like, cause we answered both your cases.

@JimiC, no problem!

Just another thing. Note that .jsx files are not associated to javascriptreact by default unless you have some language extension installed.

You sure? Cause Javascript React is natively supported by vscode.
Proof: https://github.com/Microsoft/vscode/blob/master/extensions/javascript/package.json#L25

At least is what I experience in my react projects... Is there maybe an issue with the vscode default language associations?

I've tried what @robertohuertasm said but that gave me the js icon for *.js files (yay) but the generic file icon for *.jsx files (boo). I modified it like this and it works now:

  "files.associations": {
    "*.js": "javascriptreact"
  },
  "vsicons.associations.files": [
    {
      "icon": "js",
      "extensions": ["js"],
      "format": "svg",
      "overrides": "reactjs"
    },
    {
      "icon": "reactjs",
      "extensions": ["jsx"],
      "format": "svg"
    }
  ]

@JimiC Maybe this could be put in the docs? From what I've seen many React devs use JSX in *.js files and would therefore want them to be typed as javascriptreact for code intelligence purposes but not to get a React icon on all JS files.

EDIT: To clarify: the above gives me

  • *.js files ALWAYS show up with the js icon but use javascriptreact (as set by the association)
  • *.jsx files show up with the reactjs icon and also use javascriptreact (as is the default)

@pluma have you really tried my solution? I think you have mistaken the approach and maybe copied one of @JimiC麓s proposals

Can you check again just in order to get this right?

By the way, it seems that I have some extension messing with my default .jsx files. Nevertheless, I've tried this with a clean vscode and it works!

"files.associations": {
    , "*.js": "javascriptreact"
  }
  ,"vsicons.associations.files": [
    { "icon": "js", "extensions": ["js"], "format": "svg" }
  ]

image

Both files associated to javascriptreact

@pluma You need to use @robertohuertasm 's snippet as it is.
If you don't associate the .jsx you get what you saw.

@robertohuertasm Oops, yes, yours seems to work too. Both mine and yours work and do give exactly the same result. Sorry.

FWIW this is unnecessary, I think. I'm pretty sure this is already the VSCode default:

"files.associations": {
  "*.jsx": "javascriptreact"
}

Ok. @pluma, I think your latest customization is redundant:

 {
      "icon": "reactjs",
      "extensions": ["jsx"],
      "format": "svg"
}

as this icon is already associated to jsx extension (unless you have another language extension installed messing with you).

@pluma It's unnecessary after all.
The whole thing is to override the language id we use by using

"vsicons.associations.files": [
        { "icon": "js", "extensions": ["js"], "format": "svg" }
      ]

and this is documented in https://github.com/vscode-icons/vscode-icons/wiki/FineTuning#some-examples. It's the first example.

@robertohuertasm Yes, it's redundant when using your solution. It was necessary for mine because overriding reactjs the way I did it resulted in a generic file icon for jsx. Yours doesn't have that problem.

@JimiC I'd recommend adding @robertohuertasm's solution to the docs:

  "files.associations": {
    "*.js": "javascriptreact"
  },
  "vsicons.associations.files": [
    {
      "icon": "js",
      "extensions": ["js"],
      "format": "svg"
    }
  ]

(if someone using vanilla VSCode can confirm that *.jsx maps to javascriptreact by default -- which I'm very certain about)

EDIT: Nevermind, I'm an idiot. @JimiC, you're right. I have no idea why that didn't work out for me. Maybe a big red label "use this if you want javascriptreact everywhere but keep the js icon" might help. Sorry.

(if someone using vanilla VSCode can confirm that *.jsx maps to javascriptreact by default -- which I'm very certain about)

I have already linked proof in a previous comment.

@pluma I already confirmed that:

By the way, it seems that I have some extension messing with my default .jsx files

For the record, I don't really think this use case needs further explanation in the documentation.

Yupp, @JimiC you're right. Sorry to have wasted your time. Thanks for making an awesome icon set.

You are welcome :smile:

@robertohuertasm yeah, I missed some of your comments because they were coming in at the same time while I was trying out the examples and reading what @JimiC wrote. The live updates on GitHub are a bit hard to keep track of sometimes. Sorry for the confusion.

FWIW @JimiC the first example at https://github.com/vscode-icons/vscode-icons/wiki/FineTuning#some-examples is actually this:

// Adding new extensions to an already supported icon.
// note: the format must match the existing one. If not, it will use the extension you provide.
"vsicons.associations.files": [
  { "icon": "js", "extensions": ["myExt1", "myExt2.custom.js"], "format": "svg" }
]

While this explains the general idea, it's not a real-world example. I think I initially skipped this because it seemed to only apply to adding an existing icon to _additional_ extensions, not to override existing ones. I'd like to believe I'm not the only idiot who can't connect the dots and see how this solves the problem I had.

As I was thinking in terms of "overriding" I scrolled down to find the example using overrides and then the example using extends, neither of which are appropriate for the problem at hand.

Maybe you could add a second example along the lines of

"vsicons.associations.files": [
  { "icon": "angular", "extensions": ["js"], "format": "svg" }
]

to get the point across.

What I'm saying is: now that I've tried this and I understand that it works, but without knowing that, looking at it doesn't exactly scream "this is how I can override the icon". Not when there's an actual example using the word "override" (and another with "extend") further down the list.

Well, we could add an additional example explaining what needs to be done when someone needs to "_override_" an icon that is associated to a language id. I believe @robertohuertasm is more fit to add that entry (after all he's better with words than I am).

@pluma, I can understand your concern and it makes me wonder if maybe we can add some more insights in the docs.

Here's the thing. In this case, the override works exactly the same as the first example. If you try this:

"vsicons.associations.files": [
    { "icon": "js", "extensions": ["js"], "format": "svg", "overrides": "js" }
  ]

you'll see that it works exactly the same as:

"vsicons.associations.files": [
    { "icon": "js", "extensions": ["js"], "format": "svg" }
  ]

There's a subtle difference, though.

By using the first one you override the current js association, which is using a language id association:

{ icon: 'js', extensions: [], light: true, languages: [languages.javascript], format: FileFormat.svg }

This means that the other extensions that are managed by the javascript language id will lose the js icon.

If, instead, you use the second approach, you will be only linking the js extension to the js icon and the rest of js managed extensions will continue to enjoy the js icon.

To fully understand this you will have to take a look at vscode docs regarding this matter. There you will be able to find information about the different file association types and their application order.

Basically: fileNames > fileExtensions > language Id

That means that any language id association can be overriden by a file extension association or a file name association. And that's the case that we were discussing. js and reactjs, both are managed by language id association. Thus, a simple file extension association is enough to make this work.

Maybe we can add a link to the vscode docs, to this thread and explain a little bit the association precedence.

I think pointing out the precedence and linking to the docs would definitely help. I wasn't aware this was a VSCode thing rather than a vscode-icons thing just looking at the vscode-icons docs and I'm sure neither are most people who aren't also working on VSCode icon sets or language plugins.

FWIW I also didn't understand it's possible to just _add_ another definition with the same icon without overriding/extending the existing definition matching the same icon. It wasn't clear to me these are just rules battling for precedence (like in CSS) rather than single definitions per icon (especially because "overrides" and "disabled" seem to affect all rules for that icon).

@pluma, file associations and their precendence are, indeed, a vscode api thing but the ability to customize the icons and dynamically change the file associations and even these override/extend rules are specific of vscode-icons.

Secondly, I'm not sure if I got your question right but here I go. The icon manifest generated in order to be consumed by vscode has only a one-to-one relationship between the icon and the file association type (be it name, file or language, so you can have 1 for file names, 1 for language id and 1 for file extensions). In case some dev entered more than one relationship for a specific icon and file association type (same type I mean, i.e. npm icon associated to .js and to .jsx in 2 separated entries), the last one would rule.

What we do is to abstract all this so we can write this similar to CSS (following your analogy). By using our feature you can write more than 1 relationship, no matter what type or how many times. In the end, we're going to squash all the rules you give us and merge them with the ones that we ship by default.

So yes, you could add another definition with the same icon and another file extension, for instance.

By following my previous example, in our case, you could use 2 separated entries for .js and .jsx and associate both to to the npm icon. It won't matter if you do it in one only definition or in two.

For clarity's sake:

"vsicons.associations.files": [
    { "icon": "npm", "extensions": ["js"], "format": "svg" },
    { "icon": "npm", "extensions": ["jsx"], "format": "svg" }
  ]

// is exactly the same as 

"vsicons.associations.files": [
    { "icon": "npm", "extensions": ["js", "jsx"], "format": "svg" }
 ]
Was this page helpful?
0 / 5 - 0 ratings

Related issues

iRoachie picture iRoachie  路  3Comments

chadly picture chadly  路  4Comments

robertohuertasm picture robertohuertasm  路  4Comments

cgatian picture cgatian  路  3Comments

yageek picture yageek  路  3Comments