repo-wrapped 0.0.6 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/agents/complete.agent.md +257 -0
- package/.github/agents/feature-scaffold.agent.md +248 -0
- package/.github/agents/jsdoc.agent.md +243 -0
- package/.github/agents/plan.agent.md +202 -0
- package/.github/agents/spec-writer.agent.md +169 -0
- package/.github/agents/test-writer.agent.md +169 -0
- package/.stylelintrc.json +27 -0
- package/README.md +94 -94
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +446 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +446 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +7039 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/commands/generate.js +262 -5
- package/dist/config/defaults.js +158 -0
- package/dist/config/index.js +10 -0
- package/dist/features/achievements/data/achievements.json +284 -0
- package/dist/features/achievements/engine.js +140 -0
- package/dist/features/achievements/evaluators.js +246 -0
- package/dist/features/achievements/helpers.js +58 -0
- package/dist/features/achievements/index.js +57 -0
- package/dist/features/achievements/loader.js +88 -0
- package/dist/features/achievements/template.js +155 -0
- package/dist/features/achievements/types.js +7 -0
- package/dist/features/commit-quality/analyzer.js +378 -0
- package/dist/features/commit-quality/analyzer.test.js +484 -0
- package/dist/features/commit-quality/index.js +28 -0
- package/dist/features/commit-quality/template.js +114 -0
- package/dist/features/commit-quality/types.js +2 -0
- package/dist/features/comparison/analyzer.js +222 -0
- package/dist/features/comparison/index.js +28 -0
- package/dist/features/comparison/template.js +119 -0
- package/dist/features/comparison/types.js +2 -0
- package/dist/features/contribution-graph/index.js +9 -0
- package/dist/features/contribution-graph/template.js +89 -0
- package/dist/features/events/index.js +31 -0
- package/dist/features/events/parser.js +253 -0
- package/dist/features/events/template.js +113 -0
- package/dist/features/events/types.js +2 -0
- package/dist/features/executive-summary/generator.js +275 -0
- package/dist/features/executive-summary/index.js +27 -0
- package/dist/features/executive-summary/template.js +80 -0
- package/dist/features/executive-summary/types.js +2 -0
- package/dist/features/gaps/analyzer.js +298 -0
- package/dist/features/gaps/analyzer.test.js +517 -0
- package/dist/features/gaps/index.js +27 -0
- package/dist/features/gaps/template.js +190 -0
- package/dist/features/gaps/types.js +2 -0
- package/dist/features/impact/analyzer.js +248 -0
- package/dist/features/impact/index.js +26 -0
- package/dist/features/impact/template.js +118 -0
- package/dist/features/impact/types.js +2 -0
- package/dist/features/index.js +40 -0
- package/dist/features/knowledge/analyzer.js +385 -0
- package/dist/features/knowledge/index.js +26 -0
- package/dist/features/knowledge/template.js +239 -0
- package/dist/features/knowledge/types.js +2 -0
- package/dist/features/streaks/calculator.js +184 -0
- package/dist/features/streaks/calculator.test.js +366 -0
- package/dist/features/streaks/index.js +36 -0
- package/dist/features/streaks/template.js +41 -0
- package/dist/features/streaks/types.js +9 -0
- package/dist/features/team/analyzer.js +316 -0
- package/dist/features/team/index.js +30 -0
- package/dist/features/team/template.js +146 -0
- package/dist/features/team/types.js +2 -0
- package/dist/features/time-patterns/analyzer.js +319 -0
- package/dist/features/time-patterns/analyzer.test.js +278 -0
- package/dist/features/time-patterns/index.js +37 -0
- package/dist/features/time-patterns/template.js +109 -0
- package/dist/features/time-patterns/types.js +9 -0
- package/dist/features/velocity/analyzer.js +257 -0
- package/dist/features/velocity/analyzer.test.js +383 -0
- package/dist/features/velocity/index.js +27 -0
- package/dist/features/velocity/template.js +189 -0
- package/dist/features/velocity/types.js +2 -0
- package/dist/generators/html/scripts/knowledge.js +17 -0
- package/dist/generators/html/styles/base.css +10 -6
- package/dist/generators/html/styles/components.css +121 -1
- package/dist/generators/html/styles/knowledge.css +21 -0
- package/dist/generators/html/styles/leaddev.css +1335 -0
- package/dist/generators/html/styles/strategic-insights.css +1337 -0
- package/dist/generators/html/templates/commitQualitySection.js +28 -2
- package/dist/generators/html/templates/comparisonSection.js +119 -0
- package/dist/generators/html/templates/eventsSection.js +113 -0
- package/dist/generators/html/templates/executiveSummarySection.js +80 -0
- package/dist/generators/html/templates/gapSection.js +190 -0
- package/dist/generators/html/templates/impactSection.js +8 -6
- package/dist/generators/html/templates/knowledgeSection.js +16 -2
- package/dist/generators/html/templates/teamSection.js +146 -0
- package/dist/generators/html/templates/velocitySection.js +189 -0
- package/dist/generators/html/types.js +7 -0
- package/dist/generators/html/utils/analysisRunner.js +93 -0
- package/dist/generators/html/utils/cardBuilder.js +47 -0
- package/dist/generators/html/utils/contextBuilder.js +54 -0
- package/dist/generators/html/utils/htmlDocumentBuilder.js +396 -0
- package/dist/generators/html/utils/kpiBuilder.js +76 -0
- package/dist/generators/html/utils/sectionWrapper.js +71 -0
- package/dist/generators/html/utils/styleLoader.js +2 -1
- package/dist/html/analysisRunner.js +93 -0
- package/dist/html/htmlDocumentBuilder.js +396 -0
- package/dist/html/index.js +29 -0
- package/dist/html/shared/colorUtils.js +61 -0
- package/dist/html/shared/commitMapBuilder.js +23 -0
- package/dist/html/shared/components/cardBuilder.js +47 -0
- package/dist/html/shared/components/index.js +18 -0
- package/dist/html/shared/components/kpiBuilder.js +76 -0
- package/dist/html/shared/components/sectionWrapper.js +71 -0
- package/dist/html/shared/contextBuilder.js +54 -0
- package/dist/html/shared/dateRangeCalculator.js +56 -0
- package/dist/html/shared/developerStatsCalculator.js +28 -0
- package/dist/html/shared/index.js +39 -0
- package/dist/html/shared/scriptLoader.js +15 -0
- package/dist/html/shared/scripts/export.js +125 -0
- package/dist/html/shared/scripts/knowledge.js +137 -0
- package/dist/html/shared/scripts/modal.js +68 -0
- package/dist/html/shared/scripts/navigation.js +156 -0
- package/dist/html/shared/scripts/tabs.js +18 -0
- package/dist/html/shared/scripts/tooltip.js +21 -0
- package/dist/html/shared/styleLoader.js +18 -0
- package/dist/html/shared/styles/achievements.css +387 -0
- package/dist/html/shared/styles/base.css +822 -0
- package/dist/html/shared/styles/components.css +1511 -0
- package/dist/html/shared/styles/knowledge.css +242 -0
- package/dist/html/shared/styles/strategic-insights.css +1337 -0
- package/dist/html/shared/weekGrouper.js +27 -0
- package/dist/html/types.js +7 -0
- package/dist/index.js +54 -21
- package/dist/test/helpers/commitFactory.js +166 -0
- package/dist/test/helpers/dateUtils.js +101 -0
- package/dist/test/helpers/index.js +29 -0
- package/dist/test/setup.js +17 -0
- package/dist/test/smoke.test.js +94 -0
- package/dist/types/achievements.js +7 -0
- package/dist/types/analysis.js +7 -0
- package/dist/types/core.js +7 -0
- package/dist/types/index.js +38 -0
- package/dist/types/options.js +7 -0
- package/dist/types/shared.js +7 -0
- package/dist/types/strategic.js +7 -0
- package/dist/types/summary.js +7 -0
- package/dist/utils/achievementDefinitions.js +22 -22
- package/dist/utils/analyzerContextBuilder.js +124 -0
- package/dist/utils/commitQualityAnalyzer.js +13 -2
- package/dist/utils/emptyResults.js +95 -0
- package/dist/utils/eventAnnotationParser.js +253 -0
- package/dist/utils/executiveSummaryGenerator.js +275 -0
- package/dist/utils/fileHotspotAnalyzer.js +4 -12
- package/dist/utils/gapAnalyzer.js +298 -0
- package/dist/utils/gitParser.test.js +363 -0
- package/dist/utils/htmlGenerator.js +126 -450
- package/dist/utils/impactAnalyzer.js +20 -19
- package/dist/utils/knowledgeDistributionAnalyzer.js +32 -27
- package/dist/utils/matrixGenerator.js +13 -13
- package/dist/utils/rangeComparisonAnalyzer.js +222 -0
- package/dist/utils/streakCalculator.js +77 -27
- package/dist/utils/teamAnalyzer.js +316 -0
- package/dist/utils/timePatternAnalyzer.js +18 -3
- package/dist/utils/velocityAnalyzer.js +257 -0
- package/dist/utils/wrappedGenerator.js +8 -8
- package/package.json +74 -55
- package/vitest.config.ts +46 -0
- package/dist/cli.js +0 -24
- package/dist/commands/index.js +0 -24
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTML document builder - assembles the final HTML document.
|
|
4
|
+
*
|
|
5
|
+
* @module generators/html/utils/htmlDocumentBuilder
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.buildHtmlDocument = buildHtmlDocument;
|
|
9
|
+
const date_fns_1 = require("date-fns");
|
|
10
|
+
const package_json_1 = require("../../../../package.json");
|
|
11
|
+
const styleLoader_1 = require("./styleLoader");
|
|
12
|
+
const scriptLoader_1 = require("./scriptLoader");
|
|
13
|
+
const kpiBuilder_1 = require("./kpiBuilder");
|
|
14
|
+
const sectionWrapper_1 = require("./sectionWrapper");
|
|
15
|
+
const weekGrouper_1 = require("./weekGrouper");
|
|
16
|
+
const colorUtils_1 = require("./colorUtils");
|
|
17
|
+
const contributionGraph_1 = require("../templates/contributionGraph");
|
|
18
|
+
const streaks_1 = require("../../../features/streaks");
|
|
19
|
+
const time_patterns_1 = require("../../../features/time-patterns");
|
|
20
|
+
const commitQualitySection_1 = require("../templates/commitQualitySection");
|
|
21
|
+
const achievements_1 = require("../../../features/achievements");
|
|
22
|
+
const impactSection_1 = require("../templates/impactSection");
|
|
23
|
+
const knowledgeSection_1 = require("../templates/knowledgeSection");
|
|
24
|
+
const velocitySection_1 = require("../templates/velocitySection");
|
|
25
|
+
const gapSection_1 = require("../templates/gapSection");
|
|
26
|
+
const comparisonSection_1 = require("../templates/comparisonSection");
|
|
27
|
+
const executiveSummarySection_1 = require("../templates/executiveSummarySection");
|
|
28
|
+
const teamSection_1 = require("../templates/teamSection");
|
|
29
|
+
const eventsSection_1 = require("../templates/eventsSection");
|
|
30
|
+
/**
|
|
31
|
+
* Format date range for display.
|
|
32
|
+
*/
|
|
33
|
+
function formatDateRange(start, end) {
|
|
34
|
+
return `${(0, date_fns_1.format)(start, 'MMM d, yyyy')} – ${(0, date_fns_1.format)(end, 'MMM d, yyyy')}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the overall contribution graph with month labels.
|
|
38
|
+
*/
|
|
39
|
+
function buildOverallContributionGraph(context, results) {
|
|
40
|
+
const { dateRange } = context;
|
|
41
|
+
const { commitMap, commitDetailsMap } = results.overall;
|
|
42
|
+
const weeks = (0, weekGrouper_1.groupDaysIntoWeeks)(dateRange.weekStart, dateRange.weekEnd);
|
|
43
|
+
const dayLabels = (0, weekGrouper_1.getDayLabels)();
|
|
44
|
+
const getColor = (0, colorUtils_1.createDynamicColorFn)(commitMap);
|
|
45
|
+
// Build month labels
|
|
46
|
+
let monthLabelsHtml = '';
|
|
47
|
+
let currentMonth = '';
|
|
48
|
+
weeks.forEach((week) => {
|
|
49
|
+
const firstDayOfWeek = week[0];
|
|
50
|
+
const monthName = (0, date_fns_1.format)(firstDayOfWeek, 'MMM');
|
|
51
|
+
if (monthName !== currentMonth) {
|
|
52
|
+
monthLabelsHtml += `<div class="month-label">${monthName}</div>`;
|
|
53
|
+
currentMonth = monthName;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
monthLabelsHtml += `<div class="month-label"></div>`;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
// Build week columns
|
|
60
|
+
let weekColumns = '';
|
|
61
|
+
weeks.forEach((week) => {
|
|
62
|
+
let weekColumn = `<div class="graph-column">`;
|
|
63
|
+
week.forEach((day) => {
|
|
64
|
+
const dateKey = (0, date_fns_1.format)(day, 'yyyy-MM-dd');
|
|
65
|
+
const count = commitMap.get(dateKey) || 0;
|
|
66
|
+
const isInRange = day >= dateRange.start && day <= dateRange.end;
|
|
67
|
+
const color = isInRange ? getColor(count) : 'transparent';
|
|
68
|
+
const dateStr = (0, date_fns_1.format)(day, 'MMM d, yyyy');
|
|
69
|
+
const emptyClass = count === 0 ? ' empty' : '';
|
|
70
|
+
const clickable = count > 0 ? ' clickable' : '';
|
|
71
|
+
const rawCommits = commitDetailsMap.get(dateKey) || [];
|
|
72
|
+
const sanitizedCommits = rawCommits.map(c => ({
|
|
73
|
+
...c,
|
|
74
|
+
message: c.message
|
|
75
|
+
.replace(/[\r\n]+/g, ' ')
|
|
76
|
+
.replace(/'/g, ''')
|
|
77
|
+
.replace(/"/g, '"')
|
|
78
|
+
.replace(/</g, '<')
|
|
79
|
+
.replace(/>/g, '>')
|
|
80
|
+
.substring(0, 200)
|
|
81
|
+
}));
|
|
82
|
+
const detailsData = count > 0 ? `data-details='${JSON.stringify(sanitizedCommits)}'` : '';
|
|
83
|
+
weekColumn += `<div class="day${emptyClass}${clickable}" style="background-color: ${color};" data-count="${count}" data-date="${dateStr}" ${detailsData}></div>`;
|
|
84
|
+
});
|
|
85
|
+
weekColumn += '</div>';
|
|
86
|
+
weekColumns += weekColumn;
|
|
87
|
+
});
|
|
88
|
+
// Build day labels
|
|
89
|
+
let dayLabelsHtml = '<div class="day-labels">';
|
|
90
|
+
dayLabels.forEach((label, index) => {
|
|
91
|
+
const displayLabel = [1, 3, 5].includes(index) ? label : '';
|
|
92
|
+
dayLabelsHtml += `<div class="day-label">${displayLabel}</div>`;
|
|
93
|
+
});
|
|
94
|
+
dayLabelsHtml += '</div>';
|
|
95
|
+
return `
|
|
96
|
+
<div class="graph-container">
|
|
97
|
+
<div class="months">${monthLabelsHtml}</div>
|
|
98
|
+
<div class="graph">
|
|
99
|
+
${dayLabelsHtml}
|
|
100
|
+
${weekColumns}
|
|
101
|
+
</div>
|
|
102
|
+
<div class="legend">
|
|
103
|
+
<span>Less</span>
|
|
104
|
+
<span class="legend-box" style="background-color: rgba(235, 237, 240, 0.1); border: 1px solid #21262d;"></span>
|
|
105
|
+
<span class="legend-box" style="background-color: #9be9a8;"></span>
|
|
106
|
+
<span class="legend-box" style="background-color: #40c463;"></span>
|
|
107
|
+
<span class="legend-box" style="background-color: #30a14e;"></span>
|
|
108
|
+
<span class="legend-box" style="background-color: #216e39;"></span>
|
|
109
|
+
<span>More</span>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build developer breakdown section.
|
|
116
|
+
*/
|
|
117
|
+
function buildDeveloperSection(developerStats, totalCommits) {
|
|
118
|
+
const sortedDevelopers = Array.from(developerStats.entries())
|
|
119
|
+
.sort((a, b) => b[1].commits - a[1].commits);
|
|
120
|
+
const developerAnalysisHtml = sortedDevelopers.map(([author, stats]) => {
|
|
121
|
+
const percentage = ((stats.commits / totalCommits) * 100).toFixed(1);
|
|
122
|
+
const dateRange = stats.firstCommit.toDateString() === stats.lastCommit.toDateString()
|
|
123
|
+
? (0, date_fns_1.format)(stats.firstCommit, 'MMM d, yyyy')
|
|
124
|
+
: `${(0, date_fns_1.format)(stats.firstCommit, 'MMM d, yyyy')} - ${(0, date_fns_1.format)(stats.lastCommit, 'MMM d, yyyy')}`;
|
|
125
|
+
return `
|
|
126
|
+
<div class="developer-row">
|
|
127
|
+
<div class="developer-info">
|
|
128
|
+
<div class="developer-name">${author}</div>
|
|
129
|
+
<div class="developer-date-range">${dateRange}</div>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="developer-stats">
|
|
132
|
+
<div class="developer-bar-container">
|
|
133
|
+
<div class="developer-bar" style="width: ${percentage}%"></div>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="developer-count">${stats.commits} commits (${percentage}%)</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
`;
|
|
139
|
+
}).join('');
|
|
140
|
+
return `<div class="developer-analysis">${developerAnalysisHtml}</div>`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Build personal tab content.
|
|
144
|
+
*/
|
|
145
|
+
function buildPersonalContent(context, results, skipBodyCheck) {
|
|
146
|
+
const { dateRange, currentUser } = context;
|
|
147
|
+
const { personal } = results;
|
|
148
|
+
const weeks = (0, weekGrouper_1.groupDaysIntoWeeks)(dateRange.weekStart, dateRange.weekEnd);
|
|
149
|
+
const dayLabels = (0, weekGrouper_1.getDayLabels)();
|
|
150
|
+
const kpiHeader = (0, kpiBuilder_1.buildKPIHeader)(personal.totalCommits, personal.commitQuality.overallScore, personal.streakData.currentStreak.days, personal.streakData.activeDayPercentage);
|
|
151
|
+
const contributionGraphHtml = (0, contributionGraph_1.buildContributionGraph)({
|
|
152
|
+
commitMap: personal.commitMap,
|
|
153
|
+
commitDetailsMap: personal.commitDetailsMap,
|
|
154
|
+
weeks,
|
|
155
|
+
dayLabels,
|
|
156
|
+
dataStartDate: dateRange.start,
|
|
157
|
+
dataEndDate: dateRange.end,
|
|
158
|
+
totalCommits: personal.totalCommits,
|
|
159
|
+
title: 'Your contributions',
|
|
160
|
+
getColorFn: (0, colorUtils_1.createDynamicColorFn)(personal.commitMap)
|
|
161
|
+
});
|
|
162
|
+
const streakSectionHtml = (0, streaks_1.buildStreakSection)(personal.streakData);
|
|
163
|
+
const timePatternsHtml = (0, time_patterns_1.buildTimePatternsSection)(personal.timePattern);
|
|
164
|
+
const commitQualityHtml = (0, commitQualitySection_1.buildCommitQualitySection)(personal.commitQuality, personal.totalCommits, skipBodyCheck);
|
|
165
|
+
const achievementsHtml = (0, achievements_1.buildAchievementsSection)(personal.achievementProgress);
|
|
166
|
+
return `
|
|
167
|
+
${kpiHeader}
|
|
168
|
+
${(0, sectionWrapper_1.wrapInSection)('personal-overview', 'Contribution Overview', contributionGraphHtml)}
|
|
169
|
+
${(0, sectionWrapper_1.wrapInSection)('personal-streaks', 'Streak Analysis', streakSectionHtml)}
|
|
170
|
+
${(0, sectionWrapper_1.wrapInSection)('personal-patterns', 'Time Patterns', timePatternsHtml)}
|
|
171
|
+
${(0, sectionWrapper_1.wrapInSection)('personal-quality', 'Commit Quality', commitQualityHtml)}
|
|
172
|
+
${(0, sectionWrapper_1.wrapInSection)('personal-achievements', 'Achievements', achievementsHtml)}
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Build the overall tab content.
|
|
177
|
+
*/
|
|
178
|
+
function buildOverallContent(context, results) {
|
|
179
|
+
const { developerStats } = context;
|
|
180
|
+
const { overall, impactAnalysis, knowledgeDistribution } = results;
|
|
181
|
+
const kpiHeader = (0, kpiBuilder_1.buildKPIHeader)(overall.totalCommits, overall.commitQuality.overallScore, overall.streakData.currentStreak.days, overall.streakData.activeDayPercentage);
|
|
182
|
+
const contributionGraphHtml = buildOverallContributionGraph(context, results);
|
|
183
|
+
const developerSectionHtml = buildDeveloperSection(developerStats, overall.totalCommits);
|
|
184
|
+
return `
|
|
185
|
+
${kpiHeader}
|
|
186
|
+
${(0, sectionWrapper_1.wrapInSection)('contributions', 'Contribution Activity', contributionGraphHtml)}
|
|
187
|
+
${(0, sectionWrapper_1.wrapInSection)('team-developers', 'Developer Contributions', developerSectionHtml)}
|
|
188
|
+
${impactAnalysis ? (0, sectionWrapper_1.wrapInSection)('impact', 'Developer Impact', (0, impactSection_1.buildImpactSection)(impactAnalysis)) : ''}
|
|
189
|
+
${knowledgeDistribution ? (0, sectionWrapper_1.wrapInSection)('knowledge', 'Knowledge Distribution', (0, knowledgeSection_1.buildKnowledgeSection)(knowledgeDistribution)) : ''}
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Build the strategic insights (lead dev) tab content.
|
|
194
|
+
*/
|
|
195
|
+
function buildLeadDevContent(results) {
|
|
196
|
+
const { leadDev } = results;
|
|
197
|
+
if (!leadDev)
|
|
198
|
+
return '';
|
|
199
|
+
const hasContent = leadDev.velocityAnalysis || leadDev.gapAnalysis ||
|
|
200
|
+
leadDev.rangeComparison || leadDev.executiveSummary ||
|
|
201
|
+
leadDev.teamAnalysis || (leadDev.events && leadDev.events.length > 0);
|
|
202
|
+
if (!hasContent)
|
|
203
|
+
return '';
|
|
204
|
+
return `
|
|
205
|
+
${leadDev.executiveSummary ? (0, sectionWrapper_1.wrapInSection)('executive-summary', 'Executive Summary', (0, executiveSummarySection_1.buildExecutiveSummarySection)(leadDev.executiveSummary), '📋') : ''}
|
|
206
|
+
${leadDev.velocityAnalysis ? (0, sectionWrapper_1.wrapInSection)('velocity', 'Velocity Timeline', (0, velocitySection_1.buildVelocitySection)(leadDev.velocityAnalysis), '📈') : ''}
|
|
207
|
+
${leadDev.gapAnalysis ? (0, sectionWrapper_1.wrapInSection)('gaps', 'Gap Analysis', (0, gapSection_1.buildGapSection)(leadDev.gapAnalysis), '🚧') : ''}
|
|
208
|
+
${leadDev.rangeComparison ? (0, sectionWrapper_1.wrapInSection)('comparison', 'Period Comparison', (0, comparisonSection_1.buildComparisonSection)(leadDev.rangeComparison), '⚖️') : ''}
|
|
209
|
+
${leadDev.teamAnalysis ? (0, sectionWrapper_1.wrapInSection)('team-analysis', 'Team Analysis', (0, teamSection_1.buildTeamSection)(leadDev.teamAnalysis), '👥') : ''}
|
|
210
|
+
${leadDev.events?.length ? (0, sectionWrapper_1.wrapInSection)('events', 'Event Timeline', (0, eventsSection_1.buildEventsSection)(leadDev.events), '📅') : ''}
|
|
211
|
+
`;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Build export data for JSON/CSV export.
|
|
215
|
+
*/
|
|
216
|
+
function buildExportData(context, results) {
|
|
217
|
+
const { repoInfo, currentUser, dateRange, developerStats } = context;
|
|
218
|
+
const { overall } = results;
|
|
219
|
+
return {
|
|
220
|
+
repository: repoInfo.name,
|
|
221
|
+
period: {
|
|
222
|
+
start: dateRange.start.toISOString(),
|
|
223
|
+
end: dateRange.end.toISOString()
|
|
224
|
+
},
|
|
225
|
+
author: currentUser,
|
|
226
|
+
summary: {
|
|
227
|
+
totalCommits: overall.totalCommits,
|
|
228
|
+
totalContributors: developerStats.size,
|
|
229
|
+
activeDays: overall.commitMap.size
|
|
230
|
+
},
|
|
231
|
+
streaks: {
|
|
232
|
+
currentStreak: overall.streakData.currentStreak.days,
|
|
233
|
+
longestStreak: overall.streakData.longestStreak.days,
|
|
234
|
+
totalActiveDays: overall.streakData.totalActiveDays,
|
|
235
|
+
activeDayPercentage: overall.streakData.activeDayPercentage
|
|
236
|
+
},
|
|
237
|
+
quality: {
|
|
238
|
+
overallScore: overall.commitQuality.overallScore,
|
|
239
|
+
conventionalAdherence: overall.commitQuality.conventionalCommits.adherence,
|
|
240
|
+
avgSubjectLength: overall.commitQuality.subjectQuality.avgLength
|
|
241
|
+
},
|
|
242
|
+
timePattern: {
|
|
243
|
+
chronotype: overall.timePattern.chronotype,
|
|
244
|
+
peakHour: overall.timePattern.peakHour.hour,
|
|
245
|
+
consistency: overall.timePattern.consistency?.score || 0
|
|
246
|
+
},
|
|
247
|
+
commits: Array.from(overall.commitDetailsMap.values()).flat().map((c) => ({
|
|
248
|
+
date: c.date,
|
|
249
|
+
author: c.author,
|
|
250
|
+
message: c.message.split('\n')[0],
|
|
251
|
+
hash: c.hash
|
|
252
|
+
})),
|
|
253
|
+
developerStats: Array.from(developerStats.entries()).map(([name, stats]) => ({
|
|
254
|
+
name,
|
|
255
|
+
commits: stats.commits,
|
|
256
|
+
firstCommit: stats.firstCommit.toISOString(),
|
|
257
|
+
lastCommit: stats.lastCommit.toISOString()
|
|
258
|
+
}))
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Build the complete HTML document.
|
|
263
|
+
*/
|
|
264
|
+
function buildHtmlDocument(context, results, skipBodyCheck = false) {
|
|
265
|
+
const { repoInfo, currentUser, dateRange } = context;
|
|
266
|
+
const { leadDev } = results;
|
|
267
|
+
const hasLeadDevContent = leadDev && (leadDev.velocityAnalysis || leadDev.gapAnalysis ||
|
|
268
|
+
leadDev.rangeComparison || leadDev.executiveSummary ||
|
|
269
|
+
leadDev.teamAnalysis || (leadDev.events && leadDev.events.length > 0));
|
|
270
|
+
const overallContent = buildOverallContent(context, results);
|
|
271
|
+
const personalContent = buildPersonalContent(context, results, skipBodyCheck);
|
|
272
|
+
const leadDevContent = hasLeadDevContent ? buildLeadDevContent(results) : '';
|
|
273
|
+
const exportData = buildExportData(context, results);
|
|
274
|
+
return `<!DOCTYPE html>
|
|
275
|
+
<html lang="en">
|
|
276
|
+
<head>
|
|
277
|
+
<meta charset="UTF-8">
|
|
278
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
279
|
+
<title>Git Wrapped - ${repoInfo.name}</title>
|
|
280
|
+
<style>
|
|
281
|
+
${(0, styleLoader_1.loadStyles)()}
|
|
282
|
+
</style>
|
|
283
|
+
</head>
|
|
284
|
+
<body>
|
|
285
|
+
<!-- Mobile Navigation Toggle -->
|
|
286
|
+
<button class="mobile-nav-toggle" aria-label="Toggle navigation">
|
|
287
|
+
<span class="hamburger-icon"></span>
|
|
288
|
+
</button>
|
|
289
|
+
|
|
290
|
+
<div class="dashboard-layout">
|
|
291
|
+
<!-- Sidebar Navigation -->
|
|
292
|
+
<nav class="sidebar" role="navigation" aria-label="Main navigation">
|
|
293
|
+
<div class="sidebar-header">
|
|
294
|
+
<h2>Repo-Wrapped</h2>
|
|
295
|
+
<span class="version">v${package_json_1.version}</span>
|
|
296
|
+
</div>
|
|
297
|
+
|
|
298
|
+
<div class="nav-section">
|
|
299
|
+
<div class="nav-section-title">Views</div>
|
|
300
|
+
<a href="#" class="nav-item active" data-tab="overall">
|
|
301
|
+
<span class="nav-label">Team Overview</span>
|
|
302
|
+
</a>
|
|
303
|
+
<a href="#" class="nav-item" data-tab="personal">
|
|
304
|
+
<span class="nav-label">Personal Stats</span>
|
|
305
|
+
</a>
|
|
306
|
+
${hasLeadDevContent ? `
|
|
307
|
+
<a href="#" class="nav-item" data-tab="leaddev">
|
|
308
|
+
<span class="nav-label">Strategic Insights</span>
|
|
309
|
+
</a>
|
|
310
|
+
` : ''}
|
|
311
|
+
</div>
|
|
312
|
+
|
|
313
|
+
<div class="sidebar-footer">
|
|
314
|
+
<div class="repo-info">
|
|
315
|
+
<span class="repo-name">${repoInfo.name}</span>
|
|
316
|
+
${repoInfo.url ? `<a href="${repoInfo.url}" target="_blank" class="repo-link">View Repository →</a>` : ''}
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
</nav>
|
|
320
|
+
|
|
321
|
+
<!-- Main Content Area -->
|
|
322
|
+
<main class="main-content">
|
|
323
|
+
<div class="container">
|
|
324
|
+
<header class="dashboard-header">
|
|
325
|
+
<div class="header-left">
|
|
326
|
+
<h1 class="repo-name">${repoInfo.name}</h1>
|
|
327
|
+
</div>
|
|
328
|
+
<div class="header-right">
|
|
329
|
+
<div class="export-controls">
|
|
330
|
+
<button class="btn btn-secondary btn-sm" data-export="json">Export JSON</button>
|
|
331
|
+
<button class="btn btn-secondary btn-sm" data-export="csv">Export CSV</button>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</header>
|
|
335
|
+
|
|
336
|
+
<div class="filter-bar">
|
|
337
|
+
<div class="filter-group">
|
|
338
|
+
<label class="filter-label">Period</label>
|
|
339
|
+
<span class="filter-value">${formatDateRange(dateRange.start, dateRange.end)}</span>
|
|
340
|
+
</div>
|
|
341
|
+
<div class="filter-group">
|
|
342
|
+
<label class="filter-label">Author</label>
|
|
343
|
+
<span class="filter-value">${currentUser !== 'Unknown' ? currentUser : 'All Contributors'}</span>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
|
|
347
|
+
<!-- Tab Navigation -->
|
|
348
|
+
<div class="tab-nav">
|
|
349
|
+
<button class="tab-button active" data-tab="overall">📊 Team Overview</button>
|
|
350
|
+
<button class="tab-button" data-tab="personal">👤 Personal</button>
|
|
351
|
+
${hasLeadDevContent ? '<button class="tab-button" data-tab="leaddev">📊 Strategic Insights</button>' : ''}
|
|
352
|
+
</div>
|
|
353
|
+
|
|
354
|
+
<!-- Overall Tab Content -->
|
|
355
|
+
<div class="tab-content active" id="overall-content">
|
|
356
|
+
${overallContent}
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
${hasLeadDevContent ? `
|
|
360
|
+
<!-- Lead Developer Tab Content -->
|
|
361
|
+
<div class="tab-content" id="leaddev-content">
|
|
362
|
+
${leadDevContent}
|
|
363
|
+
</div>
|
|
364
|
+
` : ''}
|
|
365
|
+
|
|
366
|
+
<!-- Personal Tab Content -->
|
|
367
|
+
<div class="tab-content" id="personal-content">
|
|
368
|
+
${personalContent}
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
</div>
|
|
372
|
+
</main>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<div class="tooltip" id="tooltip"></div>
|
|
376
|
+
|
|
377
|
+
<div class="modal" id="modal">
|
|
378
|
+
<div class="modal-content">
|
|
379
|
+
<div class="modal-header">
|
|
380
|
+
<div class="modal-title" id="modal-title"></div>
|
|
381
|
+
<button class="modal-close" id="modal-close">×</button>
|
|
382
|
+
</div>
|
|
383
|
+
<div class="commit-list" id="commit-list"></div>
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
<script>
|
|
388
|
+
window.__GITWRAPPED_DATA__ = ${JSON.stringify(exportData)};
|
|
389
|
+
</script>
|
|
390
|
+
|
|
391
|
+
<script>
|
|
392
|
+
${(0, scriptLoader_1.loadScripts)()}
|
|
393
|
+
</script>
|
|
394
|
+
</body>
|
|
395
|
+
</html>`;
|
|
396
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KPI header building utilities.
|
|
4
|
+
*
|
|
5
|
+
* @module generators/html/utils/kpiBuilder
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.calculateHealthScore = calculateHealthScore;
|
|
9
|
+
exports.buildKPIHeader = buildKPIHeader;
|
|
10
|
+
exports.buildKPIHeaderFromData = buildKPIHeaderFromData;
|
|
11
|
+
exports.buildOverallKPIHeader = buildOverallKPIHeader;
|
|
12
|
+
/**
|
|
13
|
+
* Build a KPI header card.
|
|
14
|
+
*/
|
|
15
|
+
function buildKpiCard(label, value) {
|
|
16
|
+
return `
|
|
17
|
+
<div class="kpi-card">
|
|
18
|
+
<span class="kpi-label">${label}</span>
|
|
19
|
+
<span class="kpi-value">${value}</span>
|
|
20
|
+
</div>
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Calculate a health score from various metrics.
|
|
25
|
+
*
|
|
26
|
+
* @param qualityScore - Commit quality score (0-10)
|
|
27
|
+
* @param activeDayPercentage - Percentage of active days (0-100)
|
|
28
|
+
* @param currentStreak - Current streak in days
|
|
29
|
+
* @returns Health score (0-10)
|
|
30
|
+
*/
|
|
31
|
+
function calculateHealthScore(qualityScore, activeDayPercentage, currentStreak) {
|
|
32
|
+
return ((qualityScore / 10) * 0.4 +
|
|
33
|
+
(activeDayPercentage / 100) * 0.3 +
|
|
34
|
+
Math.min(currentStreak / 30, 1) * 0.3) * 10;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a KPI header with standard metrics.
|
|
38
|
+
*
|
|
39
|
+
* @param totalCommits - Total number of commits
|
|
40
|
+
* @param qualityScore - Commit quality score (0-10)
|
|
41
|
+
* @param currentStreak - Current streak in days
|
|
42
|
+
* @param activeDayPercentage - Percentage of active days
|
|
43
|
+
* @returns HTML string for the KPI header
|
|
44
|
+
*/
|
|
45
|
+
function buildKPIHeader(totalCommits, qualityScore, currentStreak, activeDayPercentage) {
|
|
46
|
+
const healthScore = calculateHealthScore(qualityScore, activeDayPercentage, currentStreak);
|
|
47
|
+
return `
|
|
48
|
+
<header class="kpi-header">
|
|
49
|
+
${buildKpiCard('Total Commits', totalCommits.toLocaleString())}
|
|
50
|
+
${buildKpiCard('Health Score', healthScore.toFixed(1))}
|
|
51
|
+
${buildKpiCard('Current Streak', `${currentStreak}d`)}
|
|
52
|
+
${buildKpiCard('Quality', qualityScore.toFixed(1))}
|
|
53
|
+
${buildKpiCard('Active Days', `${activeDayPercentage.toFixed(0)}%`)}
|
|
54
|
+
</header>
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build a KPI header from streak and quality data.
|
|
59
|
+
* Convenience wrapper for common use case.
|
|
60
|
+
*/
|
|
61
|
+
function buildKPIHeaderFromData(totalCommits, streakData, commitQuality) {
|
|
62
|
+
return buildKPIHeader(totalCommits, commitQuality.overallScore, streakData.currentStreak.days, streakData.activeDayPercentage);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build an overview KPI header for team/overall view.
|
|
66
|
+
*/
|
|
67
|
+
function buildOverallKPIHeader(totalCommits, developerCount, activeDays, qualityScore) {
|
|
68
|
+
return `
|
|
69
|
+
<header class="kpi-header">
|
|
70
|
+
${buildKpiCard('Total Commits', totalCommits.toLocaleString())}
|
|
71
|
+
${buildKpiCard('Contributors', developerCount.toString())}
|
|
72
|
+
${buildKpiCard('Active Days', activeDays.toString())}
|
|
73
|
+
${buildKpiCard('Quality Score', qualityScore.toFixed(1))}
|
|
74
|
+
</header>
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Section wrapper utilities for dashboard sections.
|
|
4
|
+
*
|
|
5
|
+
* @module generators/html/utils/sectionWrapper
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.wrapInSection = wrapInSection;
|
|
9
|
+
exports.wrapInStaticSection = wrapInStaticSection;
|
|
10
|
+
exports.createTabButton = createTabButton;
|
|
11
|
+
exports.createTabContent = createTabContent;
|
|
12
|
+
/**
|
|
13
|
+
* Wrap content in a collapsible dashboard section.
|
|
14
|
+
*
|
|
15
|
+
* @param id - Unique section ID for targeting
|
|
16
|
+
* @param title - Section title displayed in header
|
|
17
|
+
* @param content - HTML content to wrap
|
|
18
|
+
* @param icon - Optional icon emoji to display before title
|
|
19
|
+
* @returns HTML string for the wrapped section
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const html = wrapInSection('velocity', 'Velocity Timeline', velocityContent, '📈');
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function wrapInSection(id, title, content, icon = '') {
|
|
27
|
+
return `
|
|
28
|
+
<section class="dashboard-section" id="${id}">
|
|
29
|
+
<header class="section-header" role="button" aria-expanded="true">
|
|
30
|
+
<h2>${icon ? icon + ' ' : ''}${title}</h2>
|
|
31
|
+
<span class="collapse-icon">▼</span>
|
|
32
|
+
</header>
|
|
33
|
+
<div class="section-content">
|
|
34
|
+
${content}
|
|
35
|
+
</div>
|
|
36
|
+
</section>
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wrap content in a non-collapsible section (for embedded content).
|
|
41
|
+
*/
|
|
42
|
+
function wrapInStaticSection(id, title, content, icon = '') {
|
|
43
|
+
return `
|
|
44
|
+
<section class="dashboard-section" id="${id}">
|
|
45
|
+
<header class="section-header">
|
|
46
|
+
<h2>${icon ? icon + ' ' : ''}${title}</h2>
|
|
47
|
+
</header>
|
|
48
|
+
<div class="section-content">
|
|
49
|
+
${content}
|
|
50
|
+
</div>
|
|
51
|
+
</section>
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a tab button for the tab navigation.
|
|
56
|
+
*/
|
|
57
|
+
function createTabButton(id, label, icon = '', isActive = false) {
|
|
58
|
+
const activeClass = isActive ? ' active' : '';
|
|
59
|
+
return `<button class="tab-button${activeClass}" data-tab="${id}">${icon ? icon + ' ' : ''}${label}</button>`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a tab content container.
|
|
63
|
+
*/
|
|
64
|
+
function createTabContent(id, content, isActive = false) {
|
|
65
|
+
const activeClass = isActive ? ' active' : '';
|
|
66
|
+
return `
|
|
67
|
+
<div class="tab-content${activeClass}" id="${id}-content">
|
|
68
|
+
${content}
|
|
69
|
+
</div>
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
@@ -13,5 +13,6 @@ function loadStyles() {
|
|
|
13
13
|
const componentsCSS = (0, fs_1.readFileSync)((0, path_1.join)(stylesDir, 'components.css'), 'utf-8');
|
|
14
14
|
const achievementsCSS = (0, fs_1.readFileSync)((0, path_1.join)(stylesDir, 'achievements.css'), 'utf-8');
|
|
15
15
|
const knowledgeCSS = (0, fs_1.readFileSync)((0, path_1.join)(stylesDir, 'knowledge.css'), 'utf-8');
|
|
16
|
-
|
|
16
|
+
const strategicInsightsCSS = (0, fs_1.readFileSync)((0, path_1.join)(stylesDir, 'strategic-insights.css'), 'utf-8');
|
|
17
|
+
return `${baseCSS}\n\n${componentsCSS}\n\n${achievementsCSS}\n\n${knowledgeCSS}\n\n${strategicInsightsCSS}`;
|
|
17
18
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Analysis runner - executes all analyzers with shared context.
|
|
4
|
+
*
|
|
5
|
+
* @module html/analysisRunner
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.runAllAnalyzers = runAllAnalyzers;
|
|
9
|
+
const streaks_1 = require("../features/streaks");
|
|
10
|
+
const time_patterns_1 = require("../features/time-patterns");
|
|
11
|
+
const commit_quality_1 = require("../features/commit-quality");
|
|
12
|
+
const fileHotspotAnalyzer_1 = require("../utils/fileHotspotAnalyzer");
|
|
13
|
+
const impact_1 = require("../features/impact");
|
|
14
|
+
const knowledge_1 = require("../features/knowledge");
|
|
15
|
+
const achievements_1 = require("../features/achievements");
|
|
16
|
+
const commitMapBuilder_1 = require("./shared/commitMapBuilder");
|
|
17
|
+
/**
|
|
18
|
+
* Run all analyzers for the given context.
|
|
19
|
+
*
|
|
20
|
+
* @param context - The HTML generation context
|
|
21
|
+
* @param skipBodyCheck - Whether to skip commit body validation
|
|
22
|
+
* @param deepAnalysis - Whether to enable deep analysis
|
|
23
|
+
* @param leadDevFeatures - Pre-computed strategic insights (optional)
|
|
24
|
+
* @returns Analysis results for all views
|
|
25
|
+
*/
|
|
26
|
+
function runAllAnalyzers(context, skipBodyCheck = false, deepAnalysis = false, leadDevFeatures) {
|
|
27
|
+
const { filteredCommits, personalCommits, dateRange, repoInfo } = context;
|
|
28
|
+
const { start: startDate, end: endDate } = dateRange;
|
|
29
|
+
// Create commit maps for overall
|
|
30
|
+
const { commitMap, commitDetailsMap } = (0, commitMapBuilder_1.createCommitMaps)(filteredCommits, startDate, endDate);
|
|
31
|
+
const totalCommits = Array.from(commitMap.values()).reduce((sum, count) => sum + count, 0);
|
|
32
|
+
// Create commit maps for personal
|
|
33
|
+
const { commitMap: personalCommitMap, commitDetailsMap: personalCommitDetailsMap } = (0, commitMapBuilder_1.createCommitMaps)(personalCommits, startDate, endDate);
|
|
34
|
+
const totalPersonalCommits = Array.from(personalCommitMap.values()).reduce((sum, count) => sum + count, 0);
|
|
35
|
+
// Run overall analyzers
|
|
36
|
+
const streakData = (0, streaks_1.calculateStreaks)(filteredCommits, startDate, endDate);
|
|
37
|
+
const timePattern = (0, time_patterns_1.analyzeTimePatterns)(filteredCommits, startDate, endDate);
|
|
38
|
+
const commitQuality = (0, commit_quality_1.analyzeCommitQuality)(filteredCommits, { skipBodyCheck });
|
|
39
|
+
// Run personal analyzers
|
|
40
|
+
const personalStreakData = (0, streaks_1.calculateStreaks)(personalCommits, startDate, endDate);
|
|
41
|
+
const personalTimePattern = (0, time_patterns_1.analyzeTimePatterns)(personalCommits, startDate, endDate);
|
|
42
|
+
const personalCommitQuality = (0, commit_quality_1.analyzeCommitQuality)(personalCommits, { skipBodyCheck });
|
|
43
|
+
// Run enterprise insight analyzers
|
|
44
|
+
const fileHotspots = (0, fileHotspotAnalyzer_1.analyzeFileHotspots)(repoInfo.path, startDate, endDate);
|
|
45
|
+
const impactAnalysis = (0, impact_1.analyzeImpact)(filteredCommits);
|
|
46
|
+
const knowledgeDistribution = (0, knowledge_1.analyzeKnowledgeDistribution)(filteredCommits, repoInfo.path, deepAnalysis);
|
|
47
|
+
// Build analysis data for achievements
|
|
48
|
+
const overallAnalysisData = {
|
|
49
|
+
commits: filteredCommits,
|
|
50
|
+
totalCommits,
|
|
51
|
+
streakData,
|
|
52
|
+
timePattern,
|
|
53
|
+
commitQuality,
|
|
54
|
+
fileHotspots,
|
|
55
|
+
dateRange: { start: startDate, end: endDate }
|
|
56
|
+
};
|
|
57
|
+
const personalAnalysisData = {
|
|
58
|
+
commits: personalCommits,
|
|
59
|
+
totalCommits: totalPersonalCommits,
|
|
60
|
+
streakData: personalStreakData,
|
|
61
|
+
timePattern: personalTimePattern,
|
|
62
|
+
commitQuality: personalCommitQuality,
|
|
63
|
+
fileHotspots,
|
|
64
|
+
dateRange: { start: startDate, end: endDate }
|
|
65
|
+
};
|
|
66
|
+
// Check achievements
|
|
67
|
+
const achievementProgress = (0, achievements_1.checkAchievements)(overallAnalysisData);
|
|
68
|
+
const personalAchievementProgress = (0, achievements_1.checkAchievements)(personalAnalysisData);
|
|
69
|
+
return {
|
|
70
|
+
overall: {
|
|
71
|
+
commitMap,
|
|
72
|
+
commitDetailsMap,
|
|
73
|
+
totalCommits,
|
|
74
|
+
streakData,
|
|
75
|
+
timePattern,
|
|
76
|
+
commitQuality,
|
|
77
|
+
achievementProgress,
|
|
78
|
+
},
|
|
79
|
+
personal: {
|
|
80
|
+
commitMap: personalCommitMap,
|
|
81
|
+
commitDetailsMap: personalCommitDetailsMap,
|
|
82
|
+
totalCommits: totalPersonalCommits,
|
|
83
|
+
streakData: personalStreakData,
|
|
84
|
+
timePattern: personalTimePattern,
|
|
85
|
+
commitQuality: personalCommitQuality,
|
|
86
|
+
achievementProgress: personalAchievementProgress,
|
|
87
|
+
},
|
|
88
|
+
fileHotspots,
|
|
89
|
+
impactAnalysis,
|
|
90
|
+
knowledgeDistribution,
|
|
91
|
+
leadDev: leadDevFeatures,
|
|
92
|
+
};
|
|
93
|
+
}
|