-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatically resolve includes in package readme file
Allows a package readme to simply reference other files (via relative path and optional fragment specifier), like: ``` <!-- include ../../readme.md#content --> <!-- include ../../docs/footer.md --> ``` Where the main project readme could contain a bunch of project-level info, contrib, badges, etc., which you can skip by marking a specific area as t he #content anchor: ``` # My Project // bunch of badges // building/contributing, etc. <~-- #content --> # Usage // now the real stuff we want in a package readme ``` The `footer.md` could contain project sponsors and the like, and also be reused across multiple packages. The includes must be relative (to the including file) file paths, and the fragmnet specifier is optional. If the fragment specifier does not have an "end" anchor in the included file, the file is included from the anchor definition until EOF. The includes are only resolved when the actual .nupkg is created, and via a temp file, to avoid affecting the build's incrementality (which doesn't apply to the .nupkg itself either). Fixes #210
- Loading branch information
Showing
13 changed files
with
207 additions
and
3 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
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
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,72 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace NuGetizer; | ||
|
||
public class IncludesResolver | ||
{ | ||
static readonly Regex IncludeRegex = new Regex(@"<!--\s?include\s(.*?)\s?-->", RegexOptions.Compiled); | ||
|
||
public static string Process(string filePath) | ||
{ | ||
var content = File.ReadAllText(filePath).Trim(); | ||
// Allow self-excluding files for processing. Could be useful if the file itself | ||
// documents the include/exclude mechanism, for example. | ||
if (content.StartsWith("<!-- exclude -->") || content.EndsWith("<!-- exclude -->")) | ||
return content; | ||
|
||
var replacements = new Dictionary<Regex, string>(); | ||
|
||
foreach (Match match in IncludeRegex.Matches(content)) | ||
{ | ||
var includedPath = match.Groups[1].Value.Trim(); | ||
string fragment = default; | ||
if (includedPath.Contains("#")) | ||
{ | ||
fragment = "#" + includedPath.Split('#')[1]; | ||
includedPath = includedPath.Split('#')[0]; | ||
} | ||
|
||
var includedFullPath = Path.Combine(Path.GetDirectoryName(filePath), includedPath).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); | ||
if (File.Exists(includedFullPath)) | ||
{ | ||
// Resolve nested includes | ||
var includedContent = Process(includedFullPath); | ||
if (fragment != null) | ||
{ | ||
var anchor = $"<!-- {fragment} -->"; | ||
var start = includedContent.IndexOf(anchor); | ||
if (start == -1) | ||
// Warn/error? | ||
continue; | ||
|
||
includedContent = includedContent.Substring(start); | ||
var end = includedContent.IndexOf(anchor, anchor.Length); | ||
if (end != -1) | ||
includedContent = includedContent.Substring(0, end + anchor.Length); | ||
} | ||
|
||
// see if we already have a section we previously replaced | ||
var existingRegex = new Regex(@$"<!--\s?include {includedPath}{fragment}\s?-->[\s\S]*<!-- {includedPath}{fragment} -->"); | ||
var replacement = $"<!-- include {includedPath}{fragment} -->{Environment.NewLine}{includedContent}{Environment.NewLine}<!-- {includedPath}{fragment} -->"; | ||
if (existingRegex.IsMatch(content)) | ||
replacements[existingRegex] = replacement; | ||
else | ||
replacements[new Regex(@$"<!--\s?include {includedPath}{fragment}\s?-->")] = replacement; | ||
} | ||
} | ||
|
||
if (replacements.Count > 0) | ||
{ | ||
var updated = content; | ||
foreach (var replacement in replacements) | ||
updated = replacement.Key.Replace(updated, replacement.Value); | ||
|
||
return updated.Trim(); | ||
} | ||
|
||
return content; | ||
} | ||
} |
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
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,2 @@ | ||
the-footer | ||
<!-- include ../sections.md#copyright --> |
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 @@ | ||
the-header |
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,7 @@ | ||
<!-- include Common/header.md --> | ||
|
||
<!-- include sections.md#first --> | ||
|
||
<!-- include sections.md#third --> | ||
|
||
<!-- include Common/footer.md --> |
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,15 @@ | ||
<!-- #first --> | ||
section#1 | ||
<!-- #first --> | ||
|
||
<!-- #second --> | ||
section#2 | ||
<!-- #second --> | ||
|
||
<!-- #third --> | ||
section#3 | ||
<!-- #third --> | ||
|
||
<!-- #copyright --> | ||
@kzu | ||
<!-- #copyright --> |
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
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,20 @@ | ||
using Xunit; | ||
|
||
namespace NuGetizer; | ||
|
||
public class IncludesResolverTests | ||
{ | ||
[Fact] | ||
public void ResolveIncludes() | ||
{ | ||
var content = IncludesResolver.Process("Content/readme.md"); | ||
|
||
Assert.Contains("the-header", content); | ||
Assert.Contains("the-footer", content); | ||
|
||
Assert.Contains("section#1", content); | ||
Assert.DoesNotContain("section#2", content); | ||
Assert.Contains("section#3", content); | ||
Assert.Contains("@kzu", content); | ||
} | ||
} |
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
1 change: 1 addition & 0 deletions
1
src/NuGetizer.Tests/Scenarios/given_a_library_with_content/footer.md
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 @@ | ||
|
4 changes: 3 additions & 1 deletion
4
src/NuGetizer.Tests/Scenarios/given_a_library_with_content/readme.md
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 |
---|---|---|
@@ -1 +1,3 @@ | ||
# Library | ||
# Library | ||
|
||
<!-- include footer.md --> |