Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Tech Spec for rendering README in PM UI #13200

Merged
merged 30 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
753100c
Add file for PM UI design
jgonz120 Jan 26, 2024
ecb5ec7
Update accepted/2024/[TS]PMUI-Readme-rendering.md
jgonz120 Feb 6, 2024
2872fa5
updates from PR
jgonz120 Feb 6, 2024
fd80d77
Merge branch 'dev-jgonz-pmuiReadmeRendering' of https://github.com/Nu…
jgonz120 Feb 6, 2024
c7c297e
Updated questions
jgonz120 Feb 14, 2024
1cc32a1
Updated info abotu retrieving readme
jgonz120 Mar 5, 2024
7cbad50
Update tech spec
jgonz120 Mar 7, 2024
13156d3
updated
jgonz120 Mar 11, 2024
ac75026
more updates
jgonz120 Mar 11, 2024
389f0b4
Update
jgonz120 Mar 11, 2024
20d21da
update explanation
jgonz120 Mar 11, 2024
22c42b2
Updated spec
jgonz120 Apr 16, 2024
83047e5
Update doc
jgonz120 Jul 8, 2024
0e68f5c
update questions
jgonz120 Jul 9, 2024
9699056
Update where the readme downl url will be documented
jgonz120 Jul 11, 2024
d9580d2
Add implementation details
jgonz120 Jul 30, 2024
8e10802
Added more details
jgonz120 Aug 21, 2024
a656679
Update to readmeuritemplate
jgonz120 Sep 4, 2024
fd04f14
Add note about exception handling
jgonz120 Sep 4, 2024
57bc0ad
Specify where local packages are rendered
jgonz120 Oct 8, 2024
24a65ff
update to match current implementation
jgonz120 Oct 21, 2024
2ba8d99
Update accepted/2024/[TS]PMUI-Readme-rendering.md
jgonz120 Nov 4, 2024
0befa49
Update to reflect latest versions
jgonz120 Nov 6, 2024
73923d7
Add caching
jgonz120 Nov 6, 2024
9dbf57a
Update questions
jgonz120 Nov 7, 2024
b26997d
Comments from PR
jgonz120 Nov 7, 2024
efa004d
Comments from PR
jgonz120 Nov 9, 2024
bace0ba
Rearranged a bit
jgonz120 Nov 9, 2024
42176e6
Renamed file
jgonz120 Nov 19, 2024
012864e
fix typo
jgonz120 Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions accepted/2024/PMUI-Readme-rendering.md
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.
Binary file added meta/resources/ReadMePMUI/NoReadMeFound.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added meta/resources/ReadMePMUI/NoReadmeTab.png
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.
Binary file added meta/resources/ReadMePMUI/ReadmeTab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.