Skip to content

Commit 946e648

Browse files
committed
fix: total commit counts (anuraghazra#211)
* fix: wip fix total commit counts * tests: added tests * chore: remove console logs * docs: added docs for include_all_commits * chore: increased value offset x * chore: added reference/links comments * docs: updated docs
1 parent 8a870dc commit 946e648

File tree

6 files changed

+117
-11
lines changed

6 files changed

+117
-11
lines changed

api/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = async (req, res) => {
1818
hide_rank,
1919
show_icons,
2020
count_private,
21+
include_all_commits,
2122
line_height,
2223
title_color,
2324
icon_color,
@@ -31,7 +32,11 @@ module.exports = async (req, res) => {
3132
res.setHeader("Content-Type", "image/svg+xml");
3233

3334
try {
34-
stats = await fetchStats(username, parseBoolean(count_private));
35+
stats = await fetchStats(
36+
username,
37+
parseBoolean(count_private),
38+
parseBoolean(include_all_commits)
39+
);
3540
} catch (err) {
3641
return res.send(
3742
renderError(
@@ -56,6 +61,7 @@ module.exports = async (req, res) => {
5661
hide_title: parseBoolean(hide_title),
5762
hide_border: parseBoolean(hide_border),
5863
hide_rank: parseBoolean(hide_rank),
64+
include_all_commits: parseBoolean(include_all_commits),
5965
line_height,
6066
title_color,
6167
icon_color,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"dependencies": {
2323
"dotenv": "^8.2.0",
2424
"emoji-name-map": "^1.2.8",
25+
"github-username-regex": "^1.0.0",
2526
"word-wrap": "^1.2.3"
2627
},
2728
"husky": {

readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
135135
- `hide_title` - _(boolean)_
136136
- `hide_rank` - _(boolean)_
137137
- `show_icons` - _(boolean)_
138+
- `include_total_commits` - Count total commits instead of just the current year commits _(boolean)_
138139
- `count_private` - Count private commits _(boolean)_
139140
- `line_height` - Sets the line-height between text _(number)_
140141

@@ -235,6 +236,10 @@ You can use the `&layout=compact` option to change the card design.
235236

236237
![Anurag's github stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&hide=issues&show_icons=true)
237238

239+
- Include All Commits
240+
241+
![Anurag's github stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&include_all_commits=true)
242+
238243
- Themes
239244

240245
Choose from any of the [default themes](#themes)

src/fetchStats.js

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
const { request, logger } = require("./utils");
2+
const axios = require("axios");
23
const retryer = require("./retryer");
34
const calculateRank = require("./calculateRank");
5+
const githubUsernameRegex = require("github-username-regex");
6+
47
require("dotenv").config();
58

69
const fetcher = (variables, token) => {
@@ -46,7 +49,45 @@ const fetcher = (variables, token) => {
4649
);
4750
};
4851

49-
async function fetchStats(username, count_private = false) {
52+
// https://github.com/anuraghazra/github-readme-stats/issues/92#issuecomment-661026467
53+
// https://github.com/anuraghazra/github-readme-stats/pull/211/
54+
const totalCommitsFetcher = async (username) => {
55+
if (!githubUsernameRegex.test(username)) {
56+
logger.log("Invalid username");
57+
return 0;
58+
}
59+
60+
// https://developer.github.com/v3/search/#search-commits
61+
const fetchTotalCommits = (variables, token) => {
62+
return axios({
63+
method: "get",
64+
url: `https://api.github.com/search/commits?q=author:${variables.login}`,
65+
headers: {
66+
"Content-Type": "application/json",
67+
Accept: "application/vnd.github.cloak-preview",
68+
Authorization: `bearer ${token}`,
69+
},
70+
});
71+
};
72+
73+
try {
74+
let res = await retryer(fetchTotalCommits, { login: username });
75+
if (res.data.total_count) {
76+
return res.data.total_count;
77+
}
78+
} catch (err) {
79+
logger.log(err);
80+
// just return 0 if there is something wrong so that
81+
// we don't break the whole app
82+
return 0;
83+
}
84+
};
85+
86+
async function fetchStats(
87+
username,
88+
count_private = false,
89+
include_all_commits = false
90+
) {
5091
if (!username) throw Error("Invalid username");
5192

5293
const stats = {
@@ -61,6 +102,11 @@ async function fetchStats(username, count_private = false) {
61102

62103
let res = await retryer(fetcher, { login: username });
63104

105+
let experimental_totalCommits = 0;
106+
if (include_all_commits) {
107+
experimental_totalCommits = await totalCommitsFetcher(username);
108+
}
109+
64110
if (res.data.errors) {
65111
logger.error(res.data.errors);
66112
throw Error(res.data.errors[0].message || "Could not fetch user");
@@ -72,11 +118,11 @@ async function fetchStats(username, count_private = false) {
72118
stats.name = user.name || user.login;
73119
stats.totalIssues = user.issues.totalCount;
74120

75-
stats.totalCommits = contributionCount.totalCommitContributions;
121+
stats.totalCommits =
122+
contributionCount.totalCommitContributions + experimental_totalCommits;
123+
76124
if (count_private) {
77-
stats.totalCommits =
78-
contributionCount.totalCommitContributions +
79-
contributionCount.restrictedContributionsCount;
125+
stats.totalCommits += contributionCount.restrictedContributionsCount;
80126
}
81127

82128
stats.totalPRs = user.pullRequests.totalCount;

src/renderStatsCard.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ const { getStyles } = require("./getStyles");
88
const icons = require("./icons");
99
const Card = require("./Card");
1010

11-
const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
11+
const createTextNode = ({
12+
icon,
13+
label,
14+
value,
15+
id,
16+
index,
17+
showIcons,
18+
shiftValuePos,
19+
}) => {
1220
const kValue = kFormatter(value);
1321
const staggerDelay = (index + 3) * 150;
1422

@@ -24,7 +32,12 @@ const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
2432
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
2533
${iconSvg}
2634
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
27-
<text class="stat" x="135" y="12.5" data-testid="${id}">${kValue}</text>
35+
<text
36+
class="stat"
37+
x="${shiftValuePos ? 170 : 150}"
38+
y="12.5"
39+
data-testid="${id}"
40+
>${kValue}</text>
2841
</g>
2942
`;
3043
};
@@ -45,6 +58,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
4558
hide_title = false,
4659
hide_border = false,
4760
hide_rank = false,
61+
include_all_commits = false,
4862
line_height = 25,
4963
title_color,
5064
icon_color,
@@ -74,7 +88,9 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
7488
},
7589
commits: {
7690
icon: icons.commits,
77-
label: "Total Commits",
91+
label: `Total Commits${
92+
include_all_commits ? "" : ` (${new Date().getFullYear()})`
93+
}`,
7894
value: totalCommits,
7995
id: "commits",
8096
},
@@ -107,6 +123,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
107123
...STATS[key],
108124
index,
109125
showIcons: show_icons,
126+
shiftValuePos: !include_all_commits,
110127
})
111128
);
112129

tests/fetchStats.test.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ const data = {
99
user: {
1010
name: "Anurag Hazra",
1111
repositoriesContributedTo: { totalCount: 61 },
12-
contributionsCollection: { totalCommitContributions: 100, restrictedContributionsCount: 50 },
12+
contributionsCollection: {
13+
totalCommitContributions: 100,
14+
restrictedContributionsCount: 50,
15+
},
1316
pullRequests: { totalCount: 300 },
1417
issues: { totalCount: 200 },
1518
followers: { totalCount: 100 },
@@ -102,4 +105,32 @@ describe("Test fetchStats", () => {
102105
rank,
103106
});
104107
});
105-
});
108+
109+
it("should fetch total commits", async () => {
110+
mock.onPost("https://api.github.com/graphql").reply(200, data);
111+
mock
112+
.onGet("https://api.github.com/search/commits?q=author:anuraghazra")
113+
.reply(200, { total_count: 1000 });
114+
115+
let stats = await fetchStats("anuraghazra", true, true);
116+
const rank = calculateRank({
117+
totalCommits: 1000 + 150,
118+
totalRepos: 5,
119+
followers: 100,
120+
contributions: 61,
121+
stargazers: 400,
122+
prs: 300,
123+
issues: 200,
124+
});
125+
126+
expect(stats).toStrictEqual({
127+
contributedTo: 61,
128+
name: "Anurag Hazra",
129+
totalCommits: 1000 + 150,
130+
totalIssues: 200,
131+
totalPRs: 300,
132+
totalStars: 400,
133+
rank,
134+
});
135+
});
136+
});

0 commit comments

Comments
 (0)