Example #1
0
 public DisplayPackageViewModel Setup(
     DisplayPackageViewModel viewModel,
     Package package,
     User currentUser,
     PackageDeprecation deprecation,
     RenderedReadMeResult readmeResult)
 {
     _listPackageItemViewModelFactory.Setup(viewModel, package, currentUser);
     SetupCommon(viewModel, package, pushedBy: null);
     return(SetupInternal(viewModel, package, currentUser, deprecation, readmeResult));
 }
Example #2
0
 public DisplayPackageViewModel Setup(
     DisplayPackageViewModel viewModel,
     Package package,
     IReadOnlyCollection <Package> allVersions,
     User currentUser,
     IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
     RenderedReadMeResult readmeResult)
 {
     _listPackageItemViewModelFactory.Setup(viewModel, package, currentUser);
     SetupCommon(viewModel, package, pushedBy: null, packageKeyToDeprecation: packageKeyToDeprecation);
     return(SetupInternal(viewModel, package, allVersions, currentUser, packageKeyToDeprecation, readmeResult));
 }
Example #3
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 <RenderedReadMeResult> GetReadMeHtmlAsync(Package package)
        {
            var readMeMd = await GetReadMeMdAsync(package);

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

            return(string.IsNullOrEmpty(readMeMd) ?
                   result :
                   GetReadMeHtml(readMeMd));
        }
Example #4
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 <RenderedReadMeResult> GetReadMeHtmlAsync(string readmeFileName, PackageArchiveReader packageArchiveReader, Encoding encoding)
        {
            var readmeMd = await GetReadMeMdAsync(readmeFileName, packageArchiveReader, encoding);

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

            return(string.IsNullOrEmpty(readmeMd) ?
                   result :
                   GetReadMeHtml(readmeMd));
        }
Example #5
0
        public DisplayPackageViewModel Create(
            Package package,
            User currentUser,
            PackageDeprecation deprecation,
            RenderedReadMeResult readmeResult)
        {
            var viewModel = new DisplayPackageViewModel();

            return(Setup(
                       viewModel,
                       package,
                       currentUser,
                       deprecation,
                       readmeResult));
        }
Example #6
0
        public DisplayPackageViewModel Create(
            Package package,
            IReadOnlyCollection <Package> allVersions,
            User currentUser,
            IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
            RenderedReadMeResult readmeResult)
        {
            var viewModel = new DisplayPackageViewModel();

            return(Setup(
                       viewModel,
                       package,
                       allVersions,
                       currentUser,
                       packageKeyToDeprecation,
                       readmeResult));
        }
Example #7
0
        private DisplayPackageViewModel SetupInternal(
            DisplayPackageViewModel viewModel,
            Package package,
            IReadOnlyCollection <Package> allVersions,
            User currentUser,
            IReadOnlyDictionary <int, PackageDeprecation> packageKeyToDeprecation,
            RenderedReadMeResult readmeResult)
        {
            var dependencies = package.Dependencies.ToList();

            viewModel.Dependencies         = new DependencySetsViewModel(dependencies);
            viewModel.HasSemVer2Version    = viewModel.NuGetVersion.IsSemVer2;
            viewModel.HasSemVer2Dependency = dependencies
                                             .Where(pd => !string.IsNullOrEmpty(pd.VersionSpec))
                                             .Select(pd => VersionRange.Parse(pd.VersionSpec))
                                             .Any(p => (p.HasUpperBound && p.MaxVersion.IsSemVer2) || (p.HasLowerBound && p.MinVersion.IsSemVer2));

            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));
            })
                                        .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;
            }

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

            return(viewModel);
        }
Example #8
0
        /// <summary>
        /// Get converted HTML for readme.md string content.
        /// </summary>
        /// <param name="readMeMd">ReadMe.md content.</param>
        /// <returns>HTML content.</returns>
        internal static RenderedReadMeResult GetReadMeHtml(string readMeMd)
        {
            var output = new RenderedReadMeResult()
            {
                ImagesRewritten = false,
                Content         = ""
            };

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

            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 + 1, 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;
                            }
                        }
                    }
                }
            }