Home: Self-contained NuGet Packages - Icons should be embedded in Packages

Created on 3 Apr 2015  Β·  82Comments  Β·  Source: NuGet/Home

Package Icon should be able to come form inside the package.
It should be possible to put a path in the iconUrl that is relative to the package.

Epic Pack 2 VS.Client

Most helpful comment

+1 for svg as the default

All 82 comments

_Note: Transferred from issue on CodePlex - Packages containing Icon and License_

Packages containing Icon and License

Problem Statement

Currently, the NuGet schema only allows the package author to specify the LicenseUrl and IconUrl as external URLs for the license and icon respectively. This puts the burden on the developer to find a place to host those files and update the NuSpec with their locations.

Solution

The NuGet Gallery should support unpacking a license and icon within the package folder both explicitly specified and by convention.

Details

Convention Based Approach

The convention based approach is very simple.

| File | Description |
| --- | --- |
| Icon.png | An Icon.png at the root of the package will be unpacked and used as the icon for the package |
| License.txt | A license.txt file at the root of the package will be used as the license |

Explicit Reference

Alternatively, we can support explicit references using the file:// prefixed URLs relative to the package root. For example:

<iconUrl>file://content/images/nugetIcon.png</iconUrl>

This grabs the file from the content/images folder of the package and hosts it on the server. This is useful in cases where the icon is also hosted.

Device Specific Icon Images

There a multiple places where icons are displayed.

  • NuGet Dialog (32x32)
  • NuGet.org packages list (50x50)
  • NuGet.org package details page (100x100)

We should consider a convention that allows developers to include an icon specific to each of these devices.

Proposal

Use a file extension for each.

  • Icon_dialog.png (32x32)
  • Icon_list.png (50x50)
  • Icon_details.png (100x100)

We see some customers unable to view icons as the web location of the icon image is blocked by their corporate firewall. Possible solution could be to download and serve the images from NuGet.org as a resource at the same URI as the package when an image media type is requested

To support an embedded package icon in the nupkg, it seems we only need the 32x32 icon. All other images are only served on the gallery and don't need to be in the package.

As this issue is about supporting an embedded icon in the package, it sounds to me that a convention-based icon.png in the package root could be sufficient?
IconUrl is an optional nuspec element, so not sure if we should make it required to support an embedded icon.
Perhaps we should simply fallback from IconUrl to icon.png (if present) to default nuget icon?

That's an entirely different discussion. All we need is package icon proxying over www.nuget.org.

Nope, your discussion is here: https://github.com/NuGet/NuGetGallery/issues/2613
Related,
but not the topic of this client issue 😊
So, on topic, how about this client issue?

Proposal

Use a file extension for each.

Icon_dialog.png (32x32)
Icon_list.png (50x50)
Icon_details.png (100x100)

We should specify the size in the icon name instead

icon32x32.png
icon50x50.png
icon100x100.png

We need to discuss if we require all of them, can they be updated later etc.

I'd prefer to see the scale convention used by win8 manifests used here too. this would mean that brand images can be re-used and we don't need to create even more files named differently.

We should specify the size in the icon name instead

icon32x32.png
icon50x50.png
icon100x100.png

We need to discuss if we require all of them, can they be updated later etc.

I think that just requiring the biggest required size is enough. That image can be downsized to all the other necessary resolutions.

  • Yes please, this would be fantastic.
  • Please only require single size (biggest) and do your conversion using NuGet.exe at the pack stage which then creates the needed sizes for display in the NuGet.org gallery and Visual Studio/Xamarin Studio which uses this by default.
  • By using the embedded image by default in Visual Studio/Xamarin Studio it prevents network profiling/leakage of which packages a company/developer uses. Fallback to ImageUrl if the embedded image is not found (provides legacy transition path)
  • Potentially use the most excellent library ImageResizer.NET within NuGet.exe?

Downsizing is suboptimal. There is no escape from separate files if you want decent quality. Even the official purple ".NET" icon doesn't look that great in its downsized 32x32 form.

Having the option to only provide one size and have the rest downsized is great, as long as there's a way to provide files for the different sizes separately.

The image in package details on nuget.org is 128x128, not 100x100.

image

Although, in order to have that showing with full fidelity on a high DPI display, you need a larger image. E.g. I run my display scaled at 200%. Notice the difference between a 128x128 image and a 256x256 image, even though the dimensions within the page are still 128x128:

image

For this reason, I am gradually changing all my NuGet packages to have 256x256 logos instead of 128x128. Of course, that only solves this precisely for high DPI scaling at 200%, and any other level of scaling, e.g. 125%, 150% or greater than 200% will still be suboptimal. One thing that would solve all these issues, forever, is SVG support, since that eliminates the need for image scaling entirely.

BTW - the dimensions in the package list are 48x48, not 50x50:

image

+1 for svg as the default

hi,
I'm facing issue while creating windows installer. this is the issue i'm getting

electron-windows-installer:spawn Spawning mono /var/www/html/Extraction/node_modules/electron-winstaller/vendor/nuget.exe pack /tmp/si-11702-14710-a00hji.hot6ueg66r/app.nuspec -BasePath dist/app-win32-ia32 -OutputDirectory /tmp/si-11702-14710-a00hji.hot6ueg66r -NoDefaultExcludes +3ms
No dice: Failed with exit code: 1
Output:

Unhandled Exception: System.TypeLoadException: Could not load type 'NuGet.Program' from assembly 'NuGet, Version=2.8.50926.602, Culture=neutral, PublicKeyToken=null'.
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not load type 'NuGet.Program' from assembly 'NuGet, Version=2.8.50926.602, Culture=neutral, PublicKeyToken=null'.
WARNING: The runtime version supported by this application is unavailable.
Using default runtime: v2.0.50727

Hi I must be missing something since I just canΒ΄t get a local icon to load up in VS og VSTS packages.

  1. My nuspec file contains file://Resources/myIcon.png that is 32x32 (also tried 128x128).
  2. The myIcon.png file is in the project where I have tried all combos (I can think of) of "Build Action" and "Copy to Output Directory".

I have tried searching for a solution without luck and even here in this thread its totally not clear if this is possible. Is it even?

IΒ΄m using NuGet Version: 3.5.0.1938

@sturlath AFAIK it is not possible, and that is the reason that this issue exists.

Solution

The NuGet Gallery should support unpacking a license and icon within the package folder both explicitly specified and by convention.

The solution should really have nothing to do with the nuget gallery specifically. I cant put icons on stuff in my local repo without throwing an image on a webserver somewhere on the LAN,

@johnataylor It should be possible to put a path in the iconUrl - what problem does this solve?

It solves the problem of needing a webserver _just to host an icon_.

The package is also self contained at that point. I think requiring this one piece of content to be external to the package seems inconsistent or weird to most who have tried to author packages.

@StingyJack to clarify, this path is to a folder within the package? So this is about flexibility to put the icon at a custom location versus a standard location say the package root.

I think the idea of using a file path for iconUrl was simply inspired by the way icons work today. I imagine most people would be OK if the package icon was just a specially named file at the root of the package.

@karann-msft - that spec is missing "Browse from a private repository". We have a private repo from running Nuget.Server.

To your earlier question, I dont really think I care about where in the package the icon needs to be.

Replace Icon URL with Icon, keeping it a free text field (for the MVP)

Only Most Valuable Players get to use the icon field?

You may want to fix that spelling before it becomes the next "configuration file wather "

@StingyJack "MVP", in this context, stands for Minimum Viable Product.

Just a question from one jumping in here late: Why is SVG not in the current spec, only PNG and JPG?

@karann-msft

Spec looks great, thanks for pushing this issue through!


@StingyJack

that spec is missing "Browse from a private repository". We have a private repo from running Nuget.Server.

I would assume that private NuGet servers (MyGet, NuGet.Server, Nexus, Chocolatey, etc) would all work the same as NuGet.org


@markusschaber

Why is SVG not in the current spec, only PNG and JPG?

I would suspect because SVG is non-trivial for non-web clients like Visual Studio to render.

I would assume that private NuGet servers (MyGet, NuGet.Server, Nexus, Chocolatey, etc) would all work the same as NuGet.org

So many features that I _need_ from nuget are removed with every release (ps1, tt, mutable content, 4 part version numbering, consistent restore, etc). With this omission in the spec I could reasonably assume non-nuget.org repos will go the same way, and the omission being the only notice about it.

Would it be possible to default to using icon.{known extension} if present, to avoid having to boilerplate <PackageIcon source="icon.png", target=""/> across the ecosystem?

@karann-msft - spec looks great!

Would be nice if SVG was supported - with a fallback to PNG or JPG. i.e. Would be nice if developers could include multiple image types in the same package, for example, SVG and/or PNG and/or JPG and the client can decide which one to render, based on what it supports... If client can't render SVG, then fallback to PNG or JPG, etc.

e.g. in the package root:
/icon.svg
/icon.png
/icon.jpg

@adamralph Great feedback and we considered doing that. Since multiple extensions are supported, we didn't want to cycle through to check for the presence of one and then for the next. This may have perf implications for clients.

@caioproiete @markusschaber Supporting SVG would be great and is definitely on our backlog. At present, supporting SVG will break many NuGet clients that do not support SVG. We could change the protocol that allows the client to express the supported types for icons to the server and server then provides the right format for package icons to the requesting client. But then this felt like something that's beyond the MVP and can be taken up later.

@karann-msft Great! All makes sense to me... Supporting PNG and/or JPG would be a fantastic start. Just wanted to make sure you guys leave the door open for other formats in future versions!

@karann-msft I see, thanks.

My first thought was that if we allow a list of ;-separated filenames in the source tag, this cannot be added later in a backwards compatible way if clients don't know how to parse that kind of list.

But then I realized that we could add a separate attribute, e. G. highsource="icon.svg", to the PackageIcon tag (in analogy to <img lowsrc="..." in HTML), or nested tags, so capable clients can display the high resolution image, while non-capable clients will use the pixel version by default...

Btw, if the protocol is HTTP based, there's already the http Accept header which could serve the purpose of letting the client decide which image types it supports.

@karann-msft why not bake in the default icon at packaging time? Effectively, when creating the package, the presence of icon.{known extension} in the project root would result in the same packaging action as would the presence of <PackageIcon source="icon.png", target=""/>.

@adamralph As far as I can see, this is not backwards compatible (there might be projects which happen to have an icon.png in the root directory for other reasons - I'm not sure whether it's a good idea to start exposing this image silently.

Citing "The Zen of Python":

Explicit is better than implicit.

@markusschaber

As far as I can see, this is not backwards compatible (there might be projects which happen to have an icon.png in the root directory for other reasons - I'm not sure whether it's a good idea to start exposing this image silently.

I was waiting for someone to play this card. πŸ˜‰

I agree that it is not backwards compatible, but I expect the number of affected packages to be vanishingly small, and it would only cause a minor, cosmetic, problem. The cost of fixing those packages will be much less than the cost of having to boilerplate <PackageIcon source="icon.png", target=""/> across almost very package in the entire ecosystem.

Explicit is better than implicit.

In some contexts I would strongly disagree. e.g. compare the new "SDK-style" csproj format (sensible, implicit defaults) to the old one (everything explicit).

@adamralph the potential perf impact I cited was for clients to have to cycle through to look for multiple files with different extensions when for example browsing packages from a folder based

@karann-msft just to nit pick, "cycle through" implies sequentiality, where I don't see any reason for the client not to try all 3 (or whatever number of possible fallbacks) files in parallel...

@karann-msft the location of the icon inside the package can still be baked into the package metadata. My suggestion doesn't change that. What I am saying is that when _creating_ the package, the presence of icon.{known extension} in the project folder has the same effect as <PackageIcon source="icon.{known extension}", target=""/> in the csproj file.

@adamralph I now see what you mean. What's your typical package creation workflow? Do you run pack on a folder, nuspec, or a csproj?

@karann-msft about the perf impact with "cycle through": As the client knows which file types it supports, it can filter by known extensions and choose the first hit, just while parsing the list of icon pathes, long before hitting the network. Also, it's usually only a handful of icons (I don't see any need to add more than 2 - a bitmap and a vector one). So the performance impact is not that serious.

@karann-msft I use both nuspec and csproj for creating packages.

These all sound great, but can we get <iconUrl>file://content/images/nugetIcon.png</iconUrl> to work first? That I think is the minimum for me.

@StingyJack you'd have less to do if icon.png in the root of your project were used automatically.

True, but someone would have to program that extra bit of automagic instead of just using the existing setting and uri. Either would be less than figuring out all the scaling and image format support. None of these are as important as the other open issues I have.

@markusshaber we'd rather not make package consumers take any perf hit if possible. On the authoring side, you used to specify a url before (and had to find a place to host the image), now it's a file path to an image within the package.

@adamralph would you expect only a specific file name and extension to get picked up from that known location? So only if the image is named icon.png and is placed right next to the csproj or is at the root of the folder you run pack on, it'll get picked up at pack.

@karann-msft yes, I would expect only icon.png at the root of the project/folder to be used by default. I guess you could also support icon.jpg or other extensions, but PNG will probaby take care of 99% of cases.

Thanks for the feedback @adamralph, updated the spec.

Thanks @karann-msft. The spec looks good.

@karann-msft - spec still only talks about Nuget.org and folder based repos, and even has provisions for nuget.org webmasters to block some images.

Am i reading that support for icons in private nuget repositories based on NuGet.Server is not happening and that this could break them or the packages therein (like the unwanted version normalization)? Or is it not included because private repo's themselves are not going to be supported? Or is it just an oversight?

Any update on this, please?

@josesimoes we have started working on this. I don't have a hard ETA on this yet.

Still no progress?... :(

@controlflow Happy new year! Several members of the team returned from holidays last week (I just returned from my honeymoon on the 8th). We are focusing on finishing the last bit of self-contained license related work which should be done this month. Right after, we'll pick up self-contained icon work in Feb. You'll see new tasks being created under this issue as we make progress.

@karann-msft Fantastic to hear. Thank you so much!

Any status on this issue?

@elmojo - we just finished the self-contained license story (which also included a lot of work around licenses.nuget.org as well as the client side experience). We have started working on self-contained icons. and it is currently in the technical design phase.

On a side note - I will be prsenting at the MVP summit on the 20th. If anybody here is attending, do come by and say hi!

What does the 'Epic' label signify?

Hi @adamralph This is probably related to types of dev work.
At least in terms of JIRA that I use daily:

  • bug fix/regression fix
  • task/general change/refactor
  • story / feature-addition - with user benefit

Epics are usually collections of the above types of issue that are too big to be done in one piece of work, that all follow a theme.

A starter for 10:
https://github.community/t5/How-to-use-Git-and-GitHub/Epics-amp-GitHub-issues/td-p/13493

@ncook-vero thanks for the info.

Can you offer any explanation of why this is an epic? I'm having a hard time believing "Package Icon should be able to come from inside the package" is a collection of issues that "are too big to be done in one piece of work, that all follow a theme".

Hi @adamralph

I can't give you much insight I'm afraid, as I'm a consumer of NuGet and not a producer :)

I'd rather see something broken down into tiny milestones than risk a regression by doing too much at once, though. They're probably trying to make sure they build this feature out of common code and adhere to some internal common practice, like making it the same for nuget.exe and the dotnet packager .exe.

Sorry @ncook-vero, I mistook you for a project maintainer.

Perhaps one of the project maintainers can share some insight on this.

@adamralph I'm sure @dominoFire and/or someone else in the project team can clarify, but I would _guess_ that:

  • The definition of Epic _for them_, is anything that cannot fit in a single sprint
  • They do short sprints and feel that the work would span at least two sprints

You are right. We make big features into epic and then split it into smaller work items that we can easily cost and implement within a short span of time, ideally a sprint. β€˜Big’ can either mean big in terms of cost or complexity.

If it is an epic, can the epic be split into smaller stories that deliver usable functionality each sprint?

e.g: A support for 32x32 png icon only. No resize, nothing else. Not visible in NuGet on-line, but could be visible in our 3rd party browser.

This feature is shipping (with support in dotnet.exe pack and nuget.exe pack) in NuGet 5.3.
The work that remains will be schedule for future releases.
Closing the epic issue, so this properly shows up in 5.3 release notes.

Is there any code that you have (maybe in the .UI lib) that shows how you extract/display the icon in WPF? I'm trying implement it in NuGet Package Explorer.

GreatπŸ‘ @onovotny seems bulk work is in this commit
https://github.com/NuGet/NuGet.Client/commit/c05f9afa9c2fcee7fbe10754521b3f6424bee128

@devlead Unfortunately, that commit only handles packing/generating the package. We're already using the NuGet libraries to do that, so we're good there.

What I need is the proper extraction for binding in various scenarios (IconUrl, embeded Icon, etc).

Is it possible to refer to an image in a directory outside the project? It would be very useful to do so if you have multiple NuGet packages in a solution:

    Images
        Icon.png
    Source
        Package1
            Package1.csproj
        Package2
            Package2.csproj
<PropertyGroup Label="Package">
    <!-- This is what I've tried: -->
    <PackageIcon>file://../../Images/Icon.png</PackageIcon>
    <PackageIcon>../../Images/Icon.png</PackageIcon>
</PropertyGroup>

<ItemGroup Label="Files">
    <None Include="..\..\Images\Icon.png" Pack="true" PackagePath=""/>
</ItemGroup>

However, all I've tried so far produces errors.

UPDATE

I've figured it out. This seems to work:

<PropertyGroup Label="Package">
    <PackageIcon>Icon.png</PackageIcon>
</PropertyGroup>

I think this was supported. @karann-msft would know better. And I saw the UPDATE after I typed 😁

Glad you found the right way.

The package path put the image in the root of the package.
The package icon needs to refer to the matching location.

Please take a look at the docs and suggest any improvements that would help with this case.

After seeing this, I really wanted to package an icon in my NExpect package(s). However, nuget pack is bailing out with the error:

The element 'metadata' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd' has invalid child element 'icon' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'. List of possible elements expected: 'requireLicenseAcceptance, licenseUrl, frameworkReferences, tags, repository, contentFiles, packageTypes, copyright, references, license, serviceable, developmentDependency, iconUrl, dependencies, frameworkAssemblies' in namespace 'http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd'. This validation error occurred in a 'icon' element.

My Package.nuspec contains the following:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<package>
  <metadata>
    <id>NExpect</id>
    <version>1.0.158</version>
    <title>NExpect</title>
    <authors>Davyd McColl</authors>
    <owners>Davyd McColl</owners>
    <description>&#xD;&#xD;&#xD;&#xD;
    Unit-test Framework-agnostic Expect-style assertions for .NET&#xD;&#xD;&#xD;&#xD;
    </description>
    <releaseNotes>&#xD;&#xD;&#xD;&#xD;
    </releaseNotes>
    <summary>&#xD;&#xD;&#xD;&#xD;
    Provides Expect() syntax for doing assertions in .NET. Framework-agnostic, throwing&#xD;&#xD;&#xD;&#xD;
    UnmetExpectationExceptions for failures. Assertion exception type can be overridden at run-time.&#xD;&#xD;&#xD;&#xD;
    NExpect has grammar inspired by Chai and extensibility inspired by Jasmine.&#xD;&#xD;&#xD;&#xD;
    </summary>
    <language>en-US</language>
    <projectUrl>https://github.com/fluffynuts/NExpect</projectUrl>
    <icon>icon.png</icon>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <license type="expression">BSD-3-Clause</license>
    <copyright>Copyright 2017</copyright>
    <dependencies>
      <group targetFramework="net452"/>
    </dependencies>
    <references/>
    <tags/>
  </metadata>
  <files>
    <file src="icon.png" target="" />
    <file src="bin\BuildForRelease\net452\NExpect.dll" target="lib\net452"/>
    <file src="bin\BuildForRelease\net452\NExpect.pdb" target="lib\net452"/>
    <file src="bin\BuildForRelease\netstandard2.0\NExpect.xml" target="lib\net452"/>
    <file src="bin\BuildForRelease\netstandard2.0\NExpect.dll" target="lib\netstandard2.0"/>
    <file src="bin\BuildForRelease\netstandard2.0\NExpect.xml" target="lib\netstandard2.0"/>
    <file src="bin\BuildForRelease\netstandard2.0\NExpect.pdb" target="lib\netstandard2.0"/>
    <file src="bin\BuildForRelease\netstandard2.0\NExpect.deps.json" target="lib\netstandard2.0"/>
  </files>
</package>

what am I doing wrong?

@fluffynuts you need NuGet.exe version 5.3, guess it's not blessed yet, as it's not available on nuget ( https://www.nuget.org/packages/NuGet.CommandLine/ ).

But you can download it from https://www.nuget.org/downloads

Ah, thanks -- I did a nuget update -self and got 5.2.something; I'll try with 5.3, but I'll only really be able to switch over when 5.3 is blessed as build & release are automated, including nuget update -self to ensure latest tooling at release.

Looks like our blessing we did of 5.3 missed a step. We’ll fix on Monday.

@fluffynuts are you unable to use dotnet pack? The latest SDK contains the new icon bits.

@rrelyea - can you also please publish working nuspec.xsd's?

It would be nice to get some schema based intellisense in VS for nuspec files.

@adamralph whilst I'm in the process of converting to modern projects (Project Sdk projects rather than ones mentioning toolsversion) where possible, I still have a bunch of legacy projects and afaik, dotnet <anything> isn't going to work on them?
Anyways:

  1. I can wait until Monday (:
  2. I've updated the very project I've just been working in -- had to work around multi-targeting (using Mono to provide net452), so it's nearly ready for conversion, and I'll get on it some time soon; however, I have another larger project which produces 33 packages, and that's not likely to go all-modern in a hurry (I'm not even sure how to modernis a .vbproj, and there is one in there)

This hasn't stopped my release -- I just reference the icon by url from GitHub. I was just wanting to use the new mechanism seeing as I was in the neighborhood -- I just got an icon from an #hacktoberfest PR :+1:

@SimonCropp's comment has 17 upvotes (only πŸ‘ counts). GitHub doesn't have any way for us to transfer upvotes from one issue to another (let alone a comment from an issue). So, anyone interested please upvote this issue on adding SVG support (original/first comment, not my comment). At this time, that issue only has 3 upvotes (probably because it was closed years ago, but I just reopened it).

@zivkan - Can you make a feature request through official channels for that kind of thing? I would think it would be something you would have a better time requesting than the GenPop. If not or you dont want to wait, I imagine scripting something would be the way to aggregate votes across comments and issues for the same request.

only πŸ‘ counts

Lets not have any digital gerrymandering or "chads"; πŸ‘ ❀️ πŸ˜† πŸš€ and :Hooray: are all positive reactions and should all be counted as upvotes. Excluding them would be removing > 30% of the current votes.

Microsoft may have bought GitHub, but they still operate as an external company, and I have no inside knowledge or contacts. I don't even know where external customers can request new features.

Lets not have any digital gerrymandering or "chads"; πŸ‘ ❀️ πŸ˜† πŸš€ and :Hooray: are all positive reactions and should all be counted as upvotes. Excluding them would be removing > 30% of the current votes.

GitHub doesn't provide a way to sort issues by "all positive reactions", at least that I'm aware of. Therefore, while we prioritize work on a number of factors, on GitHub I look at open issues sorted by πŸ‘ , as that appears to be the most commonly used reaction. While it would be nice to count all positive reactions, we need to be pragmatic and it's something we can't easily take into account right now. If I'm wrong, I'd be happy for someone to educate me so we can better take all reactions into account.

I'd be happy for someone to educate me so we can better take all reactions into account.

For that specific comment...

$ErrorActionPreference = 'Stop'

$headers = @{"Accept"="application/vnd.github.squirrel-girl-preview+json";}
$url = "https://api.github.com/repos/NuGet/home/issues/comments/261106692/reactions" 
$resp = Invoke-WebRequest -Headers $headers -Uri $url -UseBasicParsing
$rawResp = $resp.Content | ConvertFrom-Json
$rawResp | Group-Object -Property content | Sort-Object -Descending -Property Count | Format-Table -Property Count,Name

#####results####
Count Name  
----- ----  
   17 +1    
    5 heart 
    2 hooray
    1 laugh 

I opened a ticket with GH support on how to do this through the UI, they said its currently not possible via the UI but forwarded the request to the product team with a link to the comment above by @zivkan explaining the need.

Was this page helpful?
0 / 5 - 0 ratings