Skip to content

Commit 6cfe7eb

Browse files
committed
Trim indent/newlines in text-based package metadata
This allows having newlines in the csproj while still compacting for packing. The trimming involves: * Removing blank lines at the beginning and ending of the value * Determining indenting on the first line and using that to remove subsequent indenting in all following lines. * Applying markdown rules to remove newlines: meaning only full paragraph separating newlines (blank) will be kept. * Collapse multiple blank newlines into just one (when separating paragraphs). This means you can indent nicely in the XML (as VS does by default) while still keeping a clean and compact representation in the package. For example: ```xml <Description> Create, edit and run multiple C# top-level programs in the same project, respecting per-file `#:package` references and `#:property` 😍 </Description> ``` Would become a single line of text.
1 parent cfb04f0 commit 6cfe7eb

File tree

3 files changed

+100
-7
lines changed

3 files changed

+100
-7
lines changed

src/NuGetizer.Tasks/CreatePackage.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ public Manifest CreateManifest()
9292
metadata.DevelopmentDependency = true;
9393

9494
if (Manifest.TryGetMetadata("Title", out var title))
95-
metadata.Title = title;
95+
metadata.Title = title.TrimIndent();
9696

9797
if (Manifest.TryGetMetadata("Description", out var description))
98-
metadata.Description = description;
98+
metadata.Description = description.TrimIndent();
9999

100100
if (Manifest.TryGetMetadata("Summary", out var summary))
101-
metadata.Summary = summary;
101+
metadata.Summary = summary.TrimIndent();
102102

103103
if (Manifest.TryGetMetadata("Readme", out var readme))
104104
metadata.Readme = readme;
@@ -171,7 +171,7 @@ public Manifest CreateManifest()
171171
metadata.Icon = icon;
172172

173173
if (Manifest.TryGetMetadata("ReleaseNotes", out var releaseNotes))
174-
metadata.ReleaseNotes = releaseNotes;
174+
metadata.ReleaseNotes = releaseNotes.TrimIndent();
175175

176176
if (Manifest.TryGetMetadata("Tags", out var tags))
177177
metadata.Tags = tags;

src/NuGetizer.Tasks/Extensions.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,83 @@ public static Manifest GetManifest(this IPackageCoreReader packageReader)
131131
return null;
132132
}
133133

134+
public static string TrimIndent(this string value)
135+
{
136+
if (string.IsNullOrWhiteSpace(value))
137+
return "";
138+
139+
// Read lines without the newline characters
140+
using var sr = new StringReader(value);
141+
var lines = new List<string>();
142+
string? line;
143+
while ((line = sr.ReadLine()) != null)
144+
{
145+
lines.Add(line);
146+
}
147+
148+
// Find the first non-empty line
149+
var start = 0;
150+
while (start < lines.Count && string.IsNullOrWhiteSpace(lines[start]))
151+
{
152+
start++;
153+
}
154+
if (start == lines.Count)
155+
return "";
156+
157+
// Determine the indentation prefix from the first content line
158+
var firstContent = lines[start];
159+
var indentLen = 0;
160+
while (indentLen < firstContent.Length && char.IsWhiteSpace(firstContent[indentLen]))
161+
{
162+
indentLen++;
163+
}
164+
var indentPrefix = firstContent.Substring(0, indentLen);
165+
166+
// Find the last non-empty line
167+
var end = lines.Count - 1;
168+
while (end >= start && string.IsNullOrWhiteSpace(lines[end]))
169+
{
170+
end--;
171+
}
172+
173+
// Trim indentation from each line
174+
var trimmedLines = new List<string>();
175+
for (var i = start; i <= end; i++)
176+
{
177+
var ln = lines[i];
178+
var trimmed = ln.StartsWith(indentPrefix) ? ln.Substring(indentPrefix.Length) : ln;
179+
trimmedLines.Add(trimmed);
180+
}
181+
182+
// Collapse like Markdown: join lines within paragraphs with space, paragraphs separated by double newline
183+
var paragraphs = new List<string>();
184+
var currentPara = new List<string>();
185+
for (var i = 0; i < trimmedLines.Count; i++)
186+
{
187+
var ln = trimmedLines[i];
188+
if (string.IsNullOrWhiteSpace(ln))
189+
{
190+
if (currentPara.Count > 0)
191+
{
192+
paragraphs.Add(string.Join(" ", currentPara.Select(l => l.TrimEnd())));
193+
currentPara.Clear();
194+
}
195+
// Skip blanks, multiple blanks collapse to one break
196+
}
197+
else
198+
{
199+
currentPara.Add(ln);
200+
}
201+
}
202+
if (currentPara.Count > 0)
203+
{
204+
paragraphs.Add(string.Join(" ", currentPara.Select(l => l.TrimEnd())));
205+
}
206+
207+
// Join paragraphs with double newline
208+
return string.Join(Environment.NewLine + Environment.NewLine, paragraphs);
209+
}
210+
134211
public static void LogErrorCode(this TaskLoggingHelper log, string code, string message, params object[] messageArgs) =>
135212
log.LogError(string.Empty, code, string.Empty, string.Empty, 0, 0, 0, 0, message, messageArgs);
136213

src/NuGetizer.Tests/CreatePackageTests.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Diagnostics;
43
using System.IO;
54
using System.IO.Compression;
@@ -35,7 +34,16 @@ public CreatePackageTests(ITestOutputHelper output)
3534
{ MetadataName.PackageId, "package" },
3635
{ MetadataName.Version, "1.0.0" },
3736
{ "Title", "title" },
38-
{ "Description", "description" },
37+
{ "Description",
38+
"""
39+
40+
This is the description.
41+
Indent will be trimmed.
42+
43+
44+
New paragraph preserved.
45+
46+
""" },
3947
{ "Summary", "summary" },
4048
{ "Language", "en" },
4149

@@ -111,7 +119,6 @@ public void when_creating_package_then_contains_all_metadata()
111119
Assert.Equal(task.Manifest.GetMetadata("PackageId"), metadata.Id);
112120
Assert.Equal(task.Manifest.GetMetadata("Version"), metadata.Version.ToString());
113121
Assert.Equal(task.Manifest.GetMetadata("Title"), metadata.Title);
114-
Assert.Equal(task.Manifest.GetMetadata("Description"), metadata.Description);
115122
Assert.Equal(task.Manifest.GetMetadata("Summary"), metadata.Summary);
116123
Assert.Equal(task.Manifest.GetMetadata("Language"), metadata.Language);
117124
Assert.Equal(task.Manifest.GetMetadata("Copyright"), metadata.Copyright);
@@ -126,6 +133,15 @@ public void when_creating_package_then_contains_all_metadata()
126133
Assert.Equal(PackageType.Dependency.Name, item.Name);
127134
Assert.Equal(PackageType.EmptyVersion, item.Version);
128135
});
136+
137+
// C#-style triming is applied.
138+
Assert.Equal(
139+
"""
140+
This is the description. Indent will be trimmed.
141+
142+
New paragraph preserved.
143+
""",
144+
metadata.Description);
129145
}
130146

131147
[Fact]

0 commit comments

Comments
 (0)