Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 50 additions & 6 deletions src/PRDigest.NET/HtmlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,25 @@ public static string GenerateIndex(string archivesDir, string outputsDir)
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">{analyzerResult.PullRequestTotalCount}</div>
<div class="stat-label">マージされたPR</div>
<div class="stat-label">PR 数(Total)</div>
</div>
<div class="stat-card">
<div class="stat-value">{analyzerResult.PullRequestCountForBot}</div>
<div class="stat-label">マージされたPR(Bot)</div>
<div class="stat-value">{analyzerResult.PullRequestCountForCommunity}</div>
<div class="stat-label">PR 数(Community)</div>
</div>
<div class="stat-card">
<div class="stat-value">{analyzerResult.PullRequestCountForAiAgent}</div>
<div class="stat-label">PR 数(AI Agent)</div>
</div>
<div class="stat-card">
<div class="stat-value">{analyzerResult.PullRequestCountForBot}</div>
<div class="stat-label">PR 数(Bot)</div>
</div>
</div>
<div class="stats-label-row">
<div class="stat-card stat-card-label">
<div class="stat-value">{analyzerResult.LabelCount}</div>
<div class="stat-label">ラベル種類</div>
<div class="stat-label">ラベルタイプ数</div>
</div>
</div>
""";
Expand Down Expand Up @@ -218,6 +228,7 @@ private static string GenerateCategorizedTocHtml(PullRequestAnalyzer.AnalysisRes
var builder = new DefaultInterpolatedStringHandler(0, 0);
builder.AppendLiteral($"<h3>カテゴリ別PR一覧</h3>");
builder.AppendLiteral(Environment.NewLine);

// Community PRs (expanded)
var communityCount = analyzerResult.CommunityPullRequestMetadataSpan.Length;
builder.AppendLiteral($"<details class=\"label-group\">");
Expand All @@ -239,6 +250,25 @@ private static string GenerateCategorizedTocHtml(PullRequestAnalyzer.AnalysisRes
builder.AppendLiteral("</details>");
builder.AppendLiteral(Environment.NewLine);

// AI Agent PRs (collapsed)
var aiAgentCount = analyzerResult.AiAgentPullRequestMetadataSpan.Length;
builder.AppendLiteral("<details class=\"label-group\">");
builder.AppendLiteral(Environment.NewLine);
builder.AppendLiteral(" <summary class=\"label-group-summary\">AI Agent PRs <span class=\"label-pr-count\">(");
builder.AppendFormatted(aiAgentCount);
builder.AppendLiteral(" PRs)</span></summary>");
builder.AppendLiteral(Environment.NewLine);
builder.AppendLiteral(" <ol class=\"label-pr-list\">");
builder.AppendLiteral(Environment.NewLine);
foreach (var heading in analyzerResult.AiAgentPullRequestMetadataSpan)
{
AppendHeadingListItem(ref builder, heading);
}
builder.AppendLiteral(" </ol>");
builder.AppendLiteral(Environment.NewLine);
builder.AppendLiteral("</details>");
builder.AppendLiteral(Environment.NewLine);

// Bot PRs (collapsed)
var botCount = analyzerResult.BotPullRequestMetadataSpan.Length;
builder.AppendLiteral("<details class=\"label-group\">");
Expand Down Expand Up @@ -647,9 +677,16 @@ footer p {

.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
margin: 16px 0 24px 0;
margin: 16px 0 8px 0;
}

.stats-label-row {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
margin: 0 0 24px 0;
}

.stat-card {
Expand All @@ -658,6 +695,7 @@ footer p {
border-radius: 8px;
padding: 24px;
text-align: center;
min-width: 0;
}

.stat-value {
Expand All @@ -672,6 +710,7 @@ footer p {
font-size: 14px;
color: #6b7280;
margin-top: 4px;
overflow-wrap: break-word;
}

.view-tabs {
Expand Down Expand Up @@ -812,6 +851,11 @@ pre code {
font-size: 16px;
}

.stats-grid,
.stats-label-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.stat-value {
font-size: 28px;
}
Expand Down
28 changes: 17 additions & 11 deletions src/PRDigest.NET/PullRequestAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public static AnalysisResults Analyze(MarkdownDocument document)
var currentPosition = PullRequestPosition.None;
var tableOfContents = false;
var pullRequestTotalCount = 0;
var pullRequestCountForBot = 0;
HeadingBlock? nextPullRequestNumber = null;
HashSet<string>? pullRequestNumberTable = null;
Dictionary<string, List<Metadata>> labelTable = [];
Dictionary<string, string> labelColorMap = [];
List<Metadata> botPullRequestHeadings = [];
List<Metadata> communityPrHeadings = [];
List<Metadata> aiAgentPullRequestHeadings = [];
Metadata currentMetadata = default;
Dictionary<string, Summary> pullRequestInfoTable = [];

Expand Down Expand Up @@ -132,18 +132,20 @@ public static AnalysisResults Analyze(MarkdownDocument document)
prList.Add(currentMetadata);
}

var user = metadataList[0]?.Descendants<LiteralInline>().Skip(1).FirstOrDefault();
if (user is not null)
var userLiteralInlines = metadataList[0]?.Descendants<LiteralInline>();
if (userLiteralInlines is not null && userLiteralInlines.Any())
{
var userName = user.Content.ToString().Trim();
var userName = string.Concat(userLiteralInlines.Select(literal => literal.Content.ToString())).Trim();

// check ..[bot].. or @Copilot to count bot PRs
if (userName.EndsWith("[bot]", StringComparison.OrdinalIgnoreCase) ||
userName.IndexOf("@Copilot", StringComparison.OrdinalIgnoreCase) > -1)
// check ..[bot].. to count bot PRs, @Copilot to count AI agent PRs
if (userName.EndsWith("[bot]", StringComparison.OrdinalIgnoreCase))
{
pullRequestCountForBot++;
botPullRequestHeadings.Add(currentMetadata);
}
else if (userName.IndexOf("@Copilot", StringComparison.OrdinalIgnoreCase) > -1)
{
aiAgentPullRequestHeadings.Add(currentMetadata);
}
else
{
communityPrHeadings.Add(currentMetadata);
Expand Down Expand Up @@ -184,11 +186,11 @@ public static AnalysisResults Analyze(MarkdownDocument document)

return new AnalysisResults(
pullRequestTotalCount,
pullRequestCountForBot,
labelTable.ToFrozenDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray()),
labelColorMap.ToFrozenDictionary(),
botPullRequestHeadings,
communityPrHeadings,
aiAgentPullRequestHeadings,
pullRequestInfoTable.ToFrozenDictionary());
}

Expand Down Expand Up @@ -294,20 +296,24 @@ private static string GetOverview(ContainerInline? inline)

public sealed class AnalysisResults(
int pullRequestTotalCount,
int pullRequestCountForBot,
FrozenDictionary<string, ImmutableArray<Metadata>> labelMap,
FrozenDictionary<string, string> labelColorMap,
List<Metadata> botPullRequestMetadata,
List<Metadata> communityPullRequestMetadata,
List<Metadata> aiAgentPullRequestMetadata,
FrozenDictionary<string, Summary> summaryMap)
{
public int PullRequestTotalCount => pullRequestTotalCount;
public int PullRequestCountForBot => pullRequestCountForBot;

public int PullRequestCountForCommunity => communityPullRequestMetadata.Count;
public int PullRequestCountForBot => botPullRequestMetadata.Count;
public int PullRequestCountForAiAgent => aiAgentPullRequestMetadata.Count;
public FrozenDictionary<string, ImmutableArray<Metadata>> LabelMap => labelMap;
public FrozenDictionary<string, string> LabelColorGroups => labelColorMap;
public int LabelCount => LabelMap.Count;
public ReadOnlySpan<Metadata> CommunityPullRequestMetadataSpan => CollectionsMarshal.AsSpan(communityPullRequestMetadata);
public ReadOnlySpan<Metadata> BotPullRequestMetadataSpan => CollectionsMarshal.AsSpan(botPullRequestMetadata);
public ReadOnlySpan<Metadata> AiAgentPullRequestMetadataSpan => CollectionsMarshal.AsSpan(aiAgentPullRequestMetadata);
public FrozenDictionary<string, Summary> SummaryMap => summaryMap;
}

Expand Down