groups, ReportBranding? branding = null)
{
var sb = new StringBuilder();
sb.AppendLine("""
SharePoint Duplicate Detection Report
""");
sb.Append(BrandingHtmlHelper.BuildBrandingHeader(branding));
sb.AppendLine("""
Duplicate Detection Report
""");
sb.AppendLine($"{groups.Count:N0} duplicate group(s) found.
");
for (int i = 0; i < groups.Count; i++)
{
var g = groups[i];
int count = g.Items.Count;
string badgeClass = "badge-dup";
sb.AppendLine($"""
| # |
Library |
Path |
Size |
Created |
Modified |
""");
for (int j = 0; j < g.Items.Count; j++)
{
var item = g.Items[j];
string size = item.SizeBytes.HasValue ? FormatSize(item.SizeBytes.Value) : string.Empty;
string created = item.Created.HasValue ? item.Created.Value.ToString("yyyy-MM-dd") : string.Empty;
string modified = item.Modified.HasValue ? item.Modified.Value.ToString("yyyy-MM-dd") : string.Empty;
sb.AppendLine($"""
| {j + 1} |
{H(item.Library)} |
{H(item.Path)} |
{size} |
{created} |
{modified} |
""");
}
sb.AppendLine("""
""");
}
sb.AppendLine($"Generated: {DateTime.Now:yyyy-MM-dd HH:mm}
");
sb.AppendLine("");
return sb.ToString();
}
public async Task WriteAsync(IReadOnlyList groups, string filePath, CancellationToken ct, ReportBranding? branding = null)
{
var html = BuildHtml(groups, branding);
await System.IO.File.WriteAllTextAsync(filePath, html, Encoding.UTF8, ct);
}
private static string H(string value) =>
System.Net.WebUtility.HtmlEncode(value ?? string.Empty);
private static string FormatSize(long bytes)
{
if (bytes >= 1_073_741_824L) return $"{bytes / 1_073_741_824.0:F2} GB";
if (bytes >= 1_048_576L) return $"{bytes / 1_048_576.0:F2} MB";
if (bytes >= 1024L) return $"{bytes / 1024.0:F2} KB";
return $"{bytes} B";
}
}