public DisplayPackageViewModel Setup(
     DisplayPackageViewModel viewModel,
     Package package,
     IReadOnlyCollection <Package> allVersions,
     User currentUser,
     IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
     IReadOnlyList <PackageRename> packageRenames,
     RenderedMarkdownResult readmeResult)
 {
     _listPackageItemViewModelFactory.Setup(viewModel, package, currentUser);
     SetupCommon(viewModel, package, pushedBy: null, packageKeyToDeprecation: packageKeyToDeprecation);
     return(SetupInternal(viewModel, package, allVersions, currentUser, packageKeyToDeprecation, packageRenames, readmeResult));
 }
예제 #2
0
        /// <summary>
        /// Get the converted HTML from the stored ReadMe markdown.
        /// </summary>
        /// <param name="package">Package entity associated with the ReadMe.</param>
        /// <returns>ReadMe converted to HTML.</returns>
        public async Task <RenderedMarkdownResult> GetReadMeHtmlAsync(Package package)
        {
            var readMeMd = await GetReadMeMdAsync(package);

            var result = new RenderedMarkdownResult
            {
                Content         = readMeMd,
                ImagesRewritten = false
            };

            return(string.IsNullOrEmpty(readMeMd) ?
                   result :
                   _markdownService.GetHtmlFromMarkdown(readMeMd));
        }
예제 #3
0
        /// <summary>
        /// Get the converted HTML from the package with Readme markdown.
        /// </summary>
        /// <param name="readmeFileName">The path of Readme markdown.</param>
        /// <param name="packageArchiveReader">
        /// The <see cref="PackageArchiveReader"/> instance providing the package metadata.
        /// </param>
        /// <returns>ReadMe converted to HTML.</returns>
        public async Task <RenderedMarkdownResult> GetReadMeHtmlAsync(string readmeFileName, PackageArchiveReader packageArchiveReader, Encoding encoding)
        {
            var readmeMd = await GetReadMeMdAsync(readmeFileName, packageArchiveReader, encoding);

            var result = new RenderedMarkdownResult
            {
                Content         = readmeMd,
                ImagesRewritten = false
            };

            return(string.IsNullOrEmpty(readmeMd) ?
                   result :
                   _markdownService.GetHtmlFromMarkdown(readmeMd));
        }
        public DisplayPackageViewModel Create(
            Package package,
            IReadOnlyCollection <Package> allVersions,
            User currentUser,
            IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
            IReadOnlyList <PackageRename> packageRenames,
            RenderedMarkdownResult readmeResult)
        {
            var viewModel = new DisplayPackageViewModel();

            return(Setup(
                       viewModel,
                       package,
                       allVersions,
                       currentUser,
                       packageKeyToDeprecation,
                       packageRenames,
                       readmeResult));
        }
예제 #5
0
        public RenderedMarkdownResult GetHtmlFromMarkdown(string markdownString, int incrementHeadersBy)
        {
            var output = new RenderedMarkdownResult()
            {
                ImagesRewritten = false,
                Content         = ""
            };

            var readmeWithoutBom = markdownString.StartsWith("\ufeff") ? markdownString.Replace("\ufeff", "") : markdownString;

            // HTML encode markdown, except for block quotes, to block inline html.
            var encodedMarkdown = EncodedBlockQuotePattern.Replace(HttpUtility.HtmlEncode(readmeWithoutBom), "> ");

            var settings = CommonMarkSettings.Default.Clone();

            settings.RenderSoftLineBreaksAsLineBreaks = true;

            // Parse executes CommonMarkConverter's ProcessStage1 and ProcessStage2.
            var document = CommonMarkConverter.Parse(encodedMarkdown, settings);

            foreach (var node in document.AsEnumerable())
            {
                if (node.IsOpening)
                {
                    var block = node.Block;
                    if (block != null)
                    {
                        switch (block.Tag)
                        {
                        // Demote heading tags so they don't overpower expander headings.
                        case BlockTag.AtxHeading:
                        case BlockTag.SetextHeading:
                            var level = (byte)Math.Min(block.Heading.Level + incrementHeadersBy, 6);
                            block.Heading = new HeadingData(level);
                            break;

                        // Decode preformatted blocks to prevent double encoding.
                        // Skip BlockTag.BlockQuote, which are partially decoded upfront.
                        case BlockTag.FencedCode:
                        case BlockTag.IndentedCode:
                            if (block.StringContent != null)
                            {
                                var content          = block.StringContent.TakeFromStart(block.StringContent.Length);
                                var unencodedContent = HttpUtility.HtmlDecode(content);
                                block.StringContent.Replace(unencodedContent, 0, unencodedContent.Length);
                            }
                            break;
                        }
                    }

                    var inline = node.Inline;
                    if (inline != null)
                    {
                        if (inline.Tag == InlineTag.Link)
                        {
                            // Allow only http or https links in markdown. Transform link to https for known domains.
                            if (!PackageHelper.TryPrepareUrlForRendering(inline.TargetUrl, out string readyUriString))
                            {
                                inline.TargetUrl = string.Empty;
                            }
                            else
                            {
                                inline.TargetUrl = readyUriString;
                            }
                        }

                        else if (inline.Tag == InlineTag.Image)
                        {
                            if (!PackageHelper.TryPrepareUrlForRendering(inline.TargetUrl, out string readyUriString, rewriteAllHttp: true))
                            {
                                inline.TargetUrl = string.Empty;
                            }
                            else
                            {
                                output.ImagesRewritten = output.ImagesRewritten || (inline.TargetUrl != readyUriString);
                                inline.TargetUrl       = readyUriString;
                            }
                        }
                    }
                }
            }
        private DisplayPackageViewModel SetupInternal(
            DisplayPackageViewModel viewModel,
            Package package,
            IReadOnlyCollection <Package> allVersions,
            User currentUser,
            IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
            IReadOnlyDictionary <int, IReadOnlyList <PackageVulnerability> > packageKeyToVulnerabilities,
            IReadOnlyList <PackageRename> packageRenames,
            RenderedMarkdownResult readmeResult)
        {
            var dependencies = package.Dependencies.ToList();

            viewModel.Dependencies = new DependencySetsViewModel(dependencies);

            var packageHistory = allVersions
                                 .OrderByDescending(p => new NuGetVersion(p.Version))
                                 .ToList();
            var pushedByCache = new Dictionary <User, string>();

            viewModel.PackageVersions = packageHistory
                                        .Select(
                p =>
            {
                var vm = new DisplayPackageViewModel();
                _listPackageItemViewModelFactory.Setup(vm, p, currentUser);
                return(SetupCommon(vm, p, GetPushedBy(p, currentUser, pushedByCache), packageKeyToDeprecation, packageKeyToVulnerabilities));
            })
                                        .ToList();

            viewModel.PushedBy        = GetPushedBy(package, currentUser, pushedByCache);
            viewModel.PackageFileSize = package.PackageFileSize;

            viewModel.LatestSymbolsPackage          = package.LatestSymbolPackage();
            viewModel.LatestAvailableSymbolsPackage = viewModel.LatestSymbolsPackage != null && viewModel.LatestSymbolsPackage.StatusKey == PackageStatus.Available
                ? viewModel.LatestSymbolsPackage
                : package.LatestAvailableSymbolPackage();

            if (packageHistory.Any())
            {
                // calculate the number of days since the package registration was created
                // round to the nearest integer, with a min value of 1
                // divide the total download count by this number
                viewModel.TotalDaysSinceCreated = Convert.ToInt32(Math.Max(1, Math.Round((DateTime.UtcNow - packageHistory.Min(p => p.Created)).TotalDays)));
                viewModel.DownloadsPerDay       = viewModel.TotalDownloadCount / viewModel.TotalDaysSinceCreated; // for the package
                viewModel.DownloadsPerDayLabel  = viewModel.DownloadsPerDay < 1 ? "<1" : viewModel.DownloadsPerDay.ToNuGetNumberString();

                // Lazily load the package types from the database.
                viewModel.IsDotnetToolPackageType        = package.PackageTypes.Any(e => e.Name.Equals("DotnetTool", StringComparison.OrdinalIgnoreCase));
                viewModel.IsDotnetNewTemplatePackageType = package.PackageTypes.Any(e => e.Name.Equals("Template", StringComparison.OrdinalIgnoreCase));
            }

            if (packageKeyToDeprecation != null && packageKeyToDeprecation.TryGetValue(package.Key, out var deprecation))
            {
                viewModel.AlternatePackageId = deprecation.AlternatePackageRegistration?.Id;

                var alternatePackage = deprecation.AlternatePackage;
                if (alternatePackage != null)
                {
                    // A deprecation should not have both an alternate package registration and an alternate package.
                    // In case a deprecation does have both, we will hide the alternate package registration's ID in this model.
                    viewModel.AlternatePackageId      = alternatePackage?.Id;
                    viewModel.AlternatePackageVersion = alternatePackage?.Version;
                }

                viewModel.CustomMessage = deprecation.CustomMessage;
            }

            if (packageRenames != null && packageRenames.Count != 0)
            {
                viewModel.PackageRenames = packageRenames;
                if (package.PackageRegistration?.RenamedMessage != null)
                {
                    viewModel.RenamedMessage = package.PackageRegistration.RenamedMessage;
                }
            }

            viewModel.ReadMeHtml                  = readmeResult?.Content;
            viewModel.ReadMeImagesRewritten       = readmeResult != null ? readmeResult.ImagesRewritten : false;
            viewModel.ReadmeImageSourceDisallowed = readmeResult != null ? readmeResult.ImageSourceDisallowed : false;
            viewModel.HasEmbeddedIcon             = package.HasEmbeddedIcon;

            return(viewModel);
        }