mirror of
https://github.com/Aviortheking/codestats-readme.git
synced 2025-04-22 10:42:08 +00:00
fix: total commit counts (#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
This commit is contained in:
parent
a4486d0327
commit
416f027fae
@ -18,6 +18,7 @@ module.exports = async (req, res) => {
|
|||||||
hide_rank,
|
hide_rank,
|
||||||
show_icons,
|
show_icons,
|
||||||
count_private,
|
count_private,
|
||||||
|
include_all_commits,
|
||||||
line_height,
|
line_height,
|
||||||
title_color,
|
title_color,
|
||||||
icon_color,
|
icon_color,
|
||||||
@ -31,7 +32,11 @@ module.exports = async (req, res) => {
|
|||||||
res.setHeader("Content-Type", "image/svg+xml");
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stats = await fetchStats(username, parseBoolean(count_private));
|
stats = await fetchStats(
|
||||||
|
username,
|
||||||
|
parseBoolean(count_private),
|
||||||
|
parseBoolean(include_all_commits)
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.send(
|
return res.send(
|
||||||
renderError(
|
renderError(
|
||||||
@ -56,6 +61,7 @@ module.exports = async (req, res) => {
|
|||||||
hide_title: parseBoolean(hide_title),
|
hide_title: parseBoolean(hide_title),
|
||||||
hide_border: parseBoolean(hide_border),
|
hide_border: parseBoolean(hide_border),
|
||||||
hide_rank: parseBoolean(hide_rank),
|
hide_rank: parseBoolean(hide_rank),
|
||||||
|
include_all_commits: parseBoolean(include_all_commits),
|
||||||
line_height,
|
line_height,
|
||||||
title_color,
|
title_color,
|
||||||
icon_color,
|
icon_color,
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"emoji-name-map": "^1.2.8",
|
"emoji-name-map": "^1.2.8",
|
||||||
|
"github-username-regex": "^1.0.0",
|
||||||
"word-wrap": "^1.2.3"
|
"word-wrap": "^1.2.3"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
|
@ -135,6 +135,7 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you
|
|||||||
- `hide_title` - _(boolean)_
|
- `hide_title` - _(boolean)_
|
||||||
- `hide_rank` - _(boolean)_
|
- `hide_rank` - _(boolean)_
|
||||||
- `show_icons` - _(boolean)_
|
- `show_icons` - _(boolean)_
|
||||||
|
- `include_total_commits` - Count total commits instead of just the current year commits _(boolean)_
|
||||||
- `count_private` - Count private commits _(boolean)_
|
- `count_private` - Count private commits _(boolean)_
|
||||||
- `line_height` - Sets the line-height between text _(number)_
|
- `line_height` - Sets the line-height between text _(number)_
|
||||||
|
|
||||||
@ -235,6 +236,10 @@ You can use the `&layout=compact` option to change the card design.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
- Include All Commits
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
- Themes
|
- Themes
|
||||||
|
|
||||||
Choose from any of the [default themes](#themes)
|
Choose from any of the [default themes](#themes)
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
const { request, logger } = require("./utils");
|
const { request, logger } = require("./utils");
|
||||||
|
const axios = require("axios");
|
||||||
const retryer = require("./retryer");
|
const retryer = require("./retryer");
|
||||||
const calculateRank = require("./calculateRank");
|
const calculateRank = require("./calculateRank");
|
||||||
|
const githubUsernameRegex = require("github-username-regex");
|
||||||
|
|
||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
|
|
||||||
const fetcher = (variables, token) => {
|
const fetcher = (variables, token) => {
|
||||||
@ -46,7 +49,45 @@ const fetcher = (variables, token) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function fetchStats(username, count_private = false) {
|
// https://github.com/anuraghazra/github-readme-stats/issues/92#issuecomment-661026467
|
||||||
|
// https://github.com/anuraghazra/github-readme-stats/pull/211/
|
||||||
|
const totalCommitsFetcher = async (username) => {
|
||||||
|
if (!githubUsernameRegex.test(username)) {
|
||||||
|
logger.log("Invalid username");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://developer.github.com/v3/search/#search-commits
|
||||||
|
const fetchTotalCommits = (variables, token) => {
|
||||||
|
return axios({
|
||||||
|
method: "get",
|
||||||
|
url: `https://api.github.com/search/commits?q=author:${variables.login}`,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/vnd.github.cloak-preview",
|
||||||
|
Authorization: `bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await retryer(fetchTotalCommits, { login: username });
|
||||||
|
if (res.data.total_count) {
|
||||||
|
return res.data.total_count;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.log(err);
|
||||||
|
// just return 0 if there is something wrong so that
|
||||||
|
// we don't break the whole app
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fetchStats(
|
||||||
|
username,
|
||||||
|
count_private = false,
|
||||||
|
include_all_commits = false
|
||||||
|
) {
|
||||||
if (!username) throw Error("Invalid username");
|
if (!username) throw Error("Invalid username");
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
@ -61,6 +102,11 @@ async function fetchStats(username, count_private = false) {
|
|||||||
|
|
||||||
let res = await retryer(fetcher, { login: username });
|
let res = await retryer(fetcher, { login: username });
|
||||||
|
|
||||||
|
let experimental_totalCommits = 0;
|
||||||
|
if (include_all_commits) {
|
||||||
|
experimental_totalCommits = await totalCommitsFetcher(username);
|
||||||
|
}
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
logger.error(res.data.errors);
|
logger.error(res.data.errors);
|
||||||
throw Error(res.data.errors[0].message || "Could not fetch user");
|
throw Error(res.data.errors[0].message || "Could not fetch user");
|
||||||
@ -72,11 +118,11 @@ async function fetchStats(username, count_private = false) {
|
|||||||
stats.name = user.name || user.login;
|
stats.name = user.name || user.login;
|
||||||
stats.totalIssues = user.issues.totalCount;
|
stats.totalIssues = user.issues.totalCount;
|
||||||
|
|
||||||
stats.totalCommits = contributionCount.totalCommitContributions;
|
stats.totalCommits =
|
||||||
|
contributionCount.totalCommitContributions + experimental_totalCommits;
|
||||||
|
|
||||||
if (count_private) {
|
if (count_private) {
|
||||||
stats.totalCommits =
|
stats.totalCommits += contributionCount.restrictedContributionsCount;
|
||||||
contributionCount.totalCommitContributions +
|
|
||||||
contributionCount.restrictedContributionsCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.totalPRs = user.pullRequests.totalCount;
|
stats.totalPRs = user.pullRequests.totalCount;
|
||||||
|
@ -8,7 +8,15 @@ const { getStyles } = require("./getStyles");
|
|||||||
const icons = require("./icons");
|
const icons = require("./icons");
|
||||||
const Card = require("./Card");
|
const Card = require("./Card");
|
||||||
|
|
||||||
const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
|
const createTextNode = ({
|
||||||
|
icon,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
id,
|
||||||
|
index,
|
||||||
|
showIcons,
|
||||||
|
shiftValuePos,
|
||||||
|
}) => {
|
||||||
const kValue = kFormatter(value);
|
const kValue = kFormatter(value);
|
||||||
const staggerDelay = (index + 3) * 150;
|
const staggerDelay = (index + 3) * 150;
|
||||||
|
|
||||||
@ -24,7 +32,12 @@ const createTextNode = ({ icon, label, value, id, index, showIcons }) => {
|
|||||||
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
|
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
|
||||||
${iconSvg}
|
${iconSvg}
|
||||||
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
|
<text class="stat bold" ${labelOffset} y="12.5">${label}:</text>
|
||||||
<text class="stat" x="135" y="12.5" data-testid="${id}">${kValue}</text>
|
<text
|
||||||
|
class="stat"
|
||||||
|
x="${shiftValuePos ? 170 : 150}"
|
||||||
|
y="12.5"
|
||||||
|
data-testid="${id}"
|
||||||
|
>${kValue}</text>
|
||||||
</g>
|
</g>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
@ -45,6 +58,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
hide_title = false,
|
hide_title = false,
|
||||||
hide_border = false,
|
hide_border = false,
|
||||||
hide_rank = false,
|
hide_rank = false,
|
||||||
|
include_all_commits = false,
|
||||||
line_height = 25,
|
line_height = 25,
|
||||||
title_color,
|
title_color,
|
||||||
icon_color,
|
icon_color,
|
||||||
@ -74,7 +88,9 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
},
|
},
|
||||||
commits: {
|
commits: {
|
||||||
icon: icons.commits,
|
icon: icons.commits,
|
||||||
label: "Total Commits",
|
label: `Total Commits${
|
||||||
|
include_all_commits ? "" : ` (${new Date().getFullYear()})`
|
||||||
|
}`,
|
||||||
value: totalCommits,
|
value: totalCommits,
|
||||||
id: "commits",
|
id: "commits",
|
||||||
},
|
},
|
||||||
@ -107,6 +123,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
...STATS[key],
|
...STATS[key],
|
||||||
index,
|
index,
|
||||||
showIcons: show_icons,
|
showIcons: show_icons,
|
||||||
|
shiftValuePos: !include_all_commits,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -9,7 +9,10 @@ const data = {
|
|||||||
user: {
|
user: {
|
||||||
name: "Anurag Hazra",
|
name: "Anurag Hazra",
|
||||||
repositoriesContributedTo: { totalCount: 61 },
|
repositoriesContributedTo: { totalCount: 61 },
|
||||||
contributionsCollection: { totalCommitContributions: 100, restrictedContributionsCount: 50 },
|
contributionsCollection: {
|
||||||
|
totalCommitContributions: 100,
|
||||||
|
restrictedContributionsCount: 50,
|
||||||
|
},
|
||||||
pullRequests: { totalCount: 300 },
|
pullRequests: { totalCount: 300 },
|
||||||
issues: { totalCount: 200 },
|
issues: { totalCount: 200 },
|
||||||
followers: { totalCount: 100 },
|
followers: { totalCount: 100 },
|
||||||
@ -102,4 +105,32 @@ describe("Test fetchStats", () => {
|
|||||||
rank,
|
rank,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it("should fetch total commits", async () => {
|
||||||
|
mock.onPost("https://api.github.com/graphql").reply(200, data);
|
||||||
|
mock
|
||||||
|
.onGet("https://api.github.com/search/commits?q=author:anuraghazra")
|
||||||
|
.reply(200, { total_count: 1000 });
|
||||||
|
|
||||||
|
let stats = await fetchStats("anuraghazra", true, true);
|
||||||
|
const rank = calculateRank({
|
||||||
|
totalCommits: 1000 + 150,
|
||||||
|
totalRepos: 5,
|
||||||
|
followers: 100,
|
||||||
|
contributions: 61,
|
||||||
|
stargazers: 400,
|
||||||
|
prs: 300,
|
||||||
|
issues: 200,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(stats).toStrictEqual({
|
||||||
|
contributedTo: 61,
|
||||||
|
name: "Anurag Hazra",
|
||||||
|
totalCommits: 1000 + 150,
|
||||||
|
totalIssues: 200,
|
||||||
|
totalPRs: 300,
|
||||||
|
totalStars: 400,
|
||||||
|
rank,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user