diff --git a/src/NuGetizer.Tasks/CreatePackage.cs b/src/NuGetizer.Tasks/CreatePackage.cs index 4f55cd3c..8fd17957 100644 --- a/src/NuGetizer.Tasks/CreatePackage.cs +++ b/src/NuGetizer.Tasks/CreatePackage.cs @@ -44,6 +44,7 @@ public class CreatePackage : Task Manifest manifest; Dictionary tokens; Regex tokensExpr; + Regex linkExpr; public override bool Execute() { @@ -230,6 +231,26 @@ void GeneratePackage(Stream output = null) { // replace readme with includes replaced. var replaced = ReplaceTokens(IncludesResolver.Process(readmeFile.Source, message => Log.LogWarningCode("NG001", message))); + + if (manifest.Metadata.Repository?.Type == "git" && + !string.IsNullOrEmpty(manifest.Metadata.Repository?.Commit) && + Uri.TryCreate(manifest.Metadata.Repository.Url, UriKind.Absolute, out var uri) && + uri.Host.EndsWith("github.com")) + { + // expr to match markdown links. use named groups to capture the link text and url. + linkExpr ??= new Regex(@"\[(?[^\]]+)\]\((?[^)]+)\)", RegexOptions.None); + var repoUrl = manifest.Metadata.Repository.Url.TrimEnd('/'); + replaced = linkExpr.Replace(replaced, match => + { + var url = match.Groups["url"].Value; + if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) + return match.Value; + + var newUrl = $"{repoUrl}/blob/{manifest.Metadata.Repository.Commit}/{url.TrimStart('/')}"; + return $"[{match.Groups["text"].Value}]({newUrl})"; + }); + } + if (!replaced.Equals(File.ReadAllText(readmeFile.Source), StringComparison.Ordinal)) { var temp = Path.GetTempFileName(); diff --git a/src/NuGetizer.Tests/CreatePackageTests.cs b/src/NuGetizer.Tests/CreatePackageTests.cs index fd6a3b71..c9813088 100644 --- a/src/NuGetizer.Tests/CreatePackageTests.cs +++ b/src/NuGetizer.Tests/CreatePackageTests.cs @@ -300,6 +300,42 @@ public void when_readme_has_include_and_tokens_then_replacements_applied() Assert.Contains("NuGetizer", readme); } + [Fact] + public void when_readme_has_relativeurl_then_expands_github_url() + { + var content = Path.GetTempFileName(); + File.WriteAllText(content, "See [license](license.txt)."); + task.Contents = new[] + { + new TaskItem(content, new Metadata + { + { MetadataName.PackageId, task.Manifest.GetMetadata("Id") }, + { MetadataName.PackFolder, PackFolderKind.None }, + { MetadataName.PackagePath, "readme.md" } + }), + }; + + task.Manifest.SetMetadata("Readme", "readme.md"); + task.Manifest.SetMetadata("RepositoryType", "git"); + task.Manifest.SetMetadata("RepositoryUrl", "https://github.com/devlooped/nugetizer"); + task.Manifest.SetMetadata("RepositorySha", "9dc2cb5de"); + + createPackage = true; + ExecuteTask(out var manifest); + + Assert.NotNull(manifest); + + Assert.Equal("readme.md", manifest.Metadata.Readme); + + var file = manifest.Files.FirstOrDefault(f => Path.GetFileName(f.Target) == manifest.Metadata.Readme); + Assert.NotNull(file); + Assert.True(File.Exists(file.Source)); + + var readme = File.ReadAllText(file.Source); + + Assert.Contains("[license](https://github.com/devlooped/nugetizer/blob/9dc2cb5de/license.txt)", readme); + } + [Fact] public void when_creating_package_with_simple_dependency_then_contains_dependency_group() {