-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13200 from NuGet/dev-jgonz-pmuiReadmeRendering
Add Tech Spec for rendering README in PM UI
- Loading branch information
Showing
5 changed files
with
196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
# Markdown README Rendering in PM UI | ||
|
||
- Jonatan Gonzalez ([jgonz120](https://github.com/jgonz120)) | ||
- Issue [#12583](https://github.com/NuGet/Home/issues/12583) <!-- GitHub Issue link --> | ||
- [Feature Spec](https://github.com/NuGet/Home/blob/7943122dffa435f4daeee600efcc5b744cd2e97e/accepted/2023/PMUI-README-rendering.md) | ||
|
||
## Summary | ||
|
||
We want to update the packages pane in the PMUI to render the README for the selected package. | ||
We also need to update the Nuget Server API to provide a link to download the README directly, without having to download the nupkg first. | ||
|
||
## Motivation | ||
|
||
The README file is an essential source of information that can help customers understand what a package does. | ||
By rendering the README file directly in the PM UI, customers can easily access the information they need to determine if a package will be helpful to them while searching, browsing, and managing their projects’ packages. | ||
This enhancement streamlines the user experience and may encourage package authors to create comprehensive README documentation when customers will be more likely to rely on it for useful information about the package. | ||
|
||
## Explanation | ||
### Functional explanation | ||
|
||
The PM UI will be updated to have tabs for the Package Details and the the README. | ||
The README will be available in all the PM UI tabs. | ||
It will also be displayed for both the solution level and project level package managers. | ||
|
||
![Alt text](../../meta/resources/ReadMePMUI/ReadmeTab.png) | ||
![Alt text](../../meta/resources/ReadMePMUI/NoReadmeTab.png) | ||
|
||
#### README Tab | ||
This tab is rendered if a remote source available to download the readme or the Installed tab is selected and the selected version is found in the global packages folder. | ||
This is to ensure that users using the Browse tab will not see the README tab if they do not have a remote source that allows README downloads. | ||
|
||
If the README tab is rendered and we do not find a README then a message is rendered encouraging the user to contact the package author to upload a README. | ||
![alt text](../../meta/resources/ReadMePMUI/NoReadMeFound.png) | ||
|
||
If there is an error rendering the README then a message will be displayed for the users. | ||
|
||
#### Package Details | ||
This tab is always rendered and contains the package details information along with the Vulnerabilty and Depreciation information. | ||
|
||
#### README File Sources | ||
|
||
* ReadmeFileUrl in the [package metadata](https://learn.microsoft.com/en-us/nuget/api/registration-base-url-resource). | ||
* README direct download specified in a new resource `ReadmeUriTemplate`. | ||
* Downloaded nupkg. | ||
|
||
### Technical explanation | ||
#### Rendering Markdown | ||
|
||
We will use the `IMarkdownPreview` control to render the README in the IDE. | ||
|
||
#### Locating the README | ||
|
||
Create a new implementation of the `INuGetResource` interface, `ReadmeUriTemplateResource`. | ||
This will only be available for sources which have implemented the new `ReadmeUriTemplate` resource type. | ||
|
||
Update `IPackageSearchMetadata` to include the `ReadmeFileUrl` field. | ||
`LocalPackageSearchMetadata` will populate the field using the README location specified in the package nuspec. If the README is defined as a text file it will be rendered as if it were markdown. | ||
When a server implements the new `RegistrationsBaseUrl` resource type, then the `ReadmeFileUrl` field will be returned from the server if a README is available and be deserialized from the response. | ||
When a server implements the `ReadmeUriTemplate` resource type and `ReadmeFileUrl` is empty, it will be populated with the url to the README. | ||
|
||
#### ReadmeUriTemplate Resource Type | ||
The `ReadmeUriTemplate` resource type will be similar to the [ReportAbuseUriTemplate](https://learn.microsoft.com/en-us/nuget/api/report-abuse-resource) resource type and will provide a template for generating the README URL. | ||
|
||
```json | ||
{ | ||
"version": "3.0.0", | ||
"resources": [ | ||
..., | ||
{ | ||
"@id": "https://apidev.nugettest.org/v3/flatcontainer/{lower_id}/{lower_version}/readme", | ||
"@type": "ReadmeUriTemplate/6.13.0" | ||
}, | ||
... | ||
] | ||
} | ||
``` | ||
In code we would take the id provided and replace the {lower_id} and {lower_version} in the strings with the package we are trying to get the README for. | ||
|
||
#### New RegistrationsBaseUrl version | ||
The new version of the [package metadata](https://learn.microsoft.com/en-us/nuget/api/registration-base-url-resource) resource type will include the **ReadmeFileUrl** field. | ||
This will be a URL for downloading the README and will only be filled if a README is available to download. | ||
|
||
index.json | ||
|
||
```json | ||
{ | ||
"version": "3.0.0", | ||
"resources": [ | ||
..., | ||
{ | ||
"@id": "https://apidev.nugettest.org/v3/registration5-gz-semver2/", | ||
"@type": "RegistrationsBaseUrl/6.13.0" | ||
}, | ||
... | ||
] | ||
} | ||
``` | ||
Example Response | ||
```json | ||
{ | ||
"@id": "https://apidev.nugettest.org/v3/registration5-gz-semver2/newtonsoft.json/index.json", | ||
"items": [ | ||
{ | ||
..., | ||
"items": [ | ||
..., | ||
{ | ||
"@id": "https://apidev.nugettest.org/v3/registration5-gz-semver2/newtonsoft.json/13.0.3.json", | ||
"@type": "Package", | ||
"catalogEntry": { | ||
"@id": "https://apidev.nugettest.org/v3/catalog0/data/2024.08.19.16.55.59/newtonsoft.json.13.0.3.json", | ||
"@type": "PackageDetails", | ||
"authors": "James Newton-King", | ||
"dependencyGroups": [ ... ], | ||
"description": "Json.NET is a popular high-performance JSON framework for .NET", | ||
"iconUrl": "https://apidev.nugettest.org/v3-flatcontainer/newtonsoft.json/13.0.3/icon", | ||
"id": "Newtonsoft.Json", | ||
"language": "", | ||
"licenseExpression": "MIT", | ||
"licenseUrl": "https://dev.nugettest.org/packages/Newtonsoft.Json/13.0.3/license", | ||
"readmeUrl": "https://dev.nugettest.org/packages/Newtonsoft.Json/13.0.3#show-readme-container", | ||
//New field | ||
"readmeFileUrl": "https://apidev.nugettest.org/v3/flatcontainer/newtonsoft.json/13.0.3/readme", | ||
"listed": true, | ||
"minClientVersion": "2.12", | ||
"packageContent": "https://apidev.nugettest.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg", | ||
"projectUrl": "https://www.newtonsoft.com/json", | ||
"published": "2023-04-25T14:48:53.817+00:00", | ||
"requireLicenseAcceptance": false, | ||
"summary": "", | ||
"tags": [ | ||
"json" | ||
], | ||
"title": "Json.NET", | ||
"version": "13.0.3" | ||
}, | ||
"packageContent": "https://apidev.nugettest.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg", | ||
"registration": "https://apidev.nugettest.org/v3/registration5-gz-semver2/newtonsoft.json/index.json" | ||
}, | ||
... | ||
], | ||
... | ||
} | ||
], | ||
... | ||
} | ||
``` | ||
|
||
#### Downloading the README | ||
|
||
Update the `INuGetPackageFileService` to add a new method for downloading the README. | ||
|
||
## Drawbacks | ||
|
||
MarkdownPreview control currently marked as obsolete since the interface has not been finalized. | ||
So when an upgrade is made we may have to change how we use the control. | ||
Since this is a shared tool, we will need to coordinate with the owners if there are changes to how NuGet.org | ||
|
||
WebView2 controls always render ontop of other controls in the view. | ||
[Secnario 25254665](https://microsoft.visualstudio.com/Edge/_workitems/edit/25254665). | ||
PM UI needs to be updated to ensure items don't scroll off screen. | ||
|
||
`INuGetPackageFileService` in its current implementation cannot download files from feeds that require authentication. | ||
|
||
## Rationale and alternatives | ||
### Using `IMarkdownPreview` | ||
We want to use a centralized control so we can leverage the work already done by another team. | ||
Any improvements done to this control will benefit other components within VS. | ||
If there are any security issues found they can be fixed in a centralized location, again benefiting multiple components within VS. | ||
This control will also help with consistent markdown rendering throughout the IDE. | ||
|
||
There's risk in ensuring consistency between the MD dialect between NuGet.org and the IDE. | ||
We would need to work with the control owners to update the control, or make customizations specifically for NuGet. | ||
|
||
### Locating the README | ||
Due to concerns about performance we will not be downloading the full nupkg temporarily just to access the README. | ||
For downloading the README from a remote source we have defined two options for feeds to implement. | ||
`ReadmeUriTemplate` will be easy and quick for NuGet.org to implement. | ||
Since we want to provide flexibility of choice to the servers, a new `RegistrationsBaseUrl` version will be defined. | ||
Servers can then choose to implement the option that best suites their architecture. | ||
|
||
## Prior Art | ||
The IMarkdownPreview is currently being used when creating a new pull request inside of Visual Studio. | ||
![Alt text](../../meta/resources/READMEPMUI/PullRequestExperience.png) | ||
|
||
nuget.org currently renders the README and our users will expect them to look the same. | ||
Ex. https://www.nuget.org/packages/Newtonsoft.Json#README-body-tab | ||
|
||
## Future Possibilities | ||
Investigate ways for encouraging package owners to publish READMEs through this experience. | ||
|
||
Implement the option for users to opt out of rendering all images from README, similar to outlook with external images. | ||
|
||
Update `INuGetPackageFileService` to allow for authenticated feeds. | ||
|
||
Add caching to avoid downloading the README multiple times for the same URL. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.