Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1170: Allow customizable width for GitHub Stats Card #1334

Merged
2 changes: 2 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = async (req, res) => {
hide,
hide_title,
hide_border,
card_width,
hide_rank,
show_icons,
count_private,
Expand Down Expand Up @@ -67,6 +68,7 @@ module.exports = async (req, res) => {
show_icons: parseBoolean(show_icons),
hide_title: parseBoolean(hide_title),
hide_border: parseBoolean(hide_border),
card_width: parseInt(card_width, 10),
hide_rank: parseBoolean(hide_rank),
include_all_commits: parseBoolean(include_all_commits),
line_height,
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ You can provide multiple comma-separated values in bg_color option to render a g

- `hide` - Hides the specified items from stats _(Comma-separated values)_
- `hide_title` - _(boolean)_
- `card_width` - Set the card's width manually _(number)_
- `hide_rank` - _(boolean)_ hides the rank and automatically resizes the card width
- `show_icons` - _(boolean)_
- `include_all_commits` - Count total commits instead of just the current year commits _(boolean)_
Expand Down
61 changes: 36 additions & 25 deletions src/cards/stats-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
show_icons = false,
hide_title = false,
hide_border = false,
card_width,
hide_rank = false,
include_all_commits = false,
line_height = 25,
Expand All @@ -75,6 +76,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
disable_animations = false,
} = options;


const lheight = parseInt(line_height, 10);

// returns theme based colors with proper overrides and defaults
Expand Down Expand Up @@ -168,26 +170,6 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
hide_rank ? 0 : 150,
);

// Conditionally rendered elements
const rankCircle = hide_rank
? ""
: `<g data-testid="rank-circle"
transform="translate(400, ${height / 2 - 50})">
<circle class="rank-circle-rim" cx="-10" cy="8" r="40" />
<circle class="rank-circle" cx="-10" cy="8" r="40" />
<g class="rank-text">
<text
x="${rank.level.length === 1 ? "-4" : "0"}"
y="0"
alignment-baseline="central"
dominant-baseline="central"
text-anchor="middle"
>
${rank.level}
</text>
</g>
</g>`;

// the better user's score the the rank will be closer to zero so
// subtracting 100 to get the progress in 100%
const progress = 100 - rank.score;
Expand All @@ -203,13 +185,22 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
return measureText(custom_title ? custom_title : i18n.t("statcard.title"));
};

const width = hide_rank
/*
When hide_rank=true, minimum card width is max of 270 and length of title + paddings.
rickstaa marked this conversation as resolved.
Show resolved Hide resolved
When hide_rank=false, minimum card_width is 340.
Numbers are picked by looking at existing dimensions on production.
*/
const minCardWidth = hide_rank
? clampValue(
50 /* padding */ + calculateTextWidth() * 2,
270 /* min */,
Infinity,
)
: 495;
270,
Infinity)
: 340
rickstaa marked this conversation as resolved.
Show resolved Hide resolved
const defaultCardWidth = hide_rank ? 270 : 495
let width = isNaN(card_width) ? defaultCardWidth : card_width
if (width < minCardWidth) {
width = minCardWidth
}

const card = new Card({
customTitle: custom_title,
Expand All @@ -232,6 +223,26 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {

if (disable_animations) card.disableAnimations();

// Conditionally rendered elements
const rankCircle = hide_rank
? ""
: `<g data-testid="rank-circle"
transform="translate(${width - 50}, ${height / 2 - 50})">
<circle class="rank-circle-rim" cx="-10" cy="8" r="40" />
<circle class="rank-circle" cx="-10" cy="8" r="40" />
<g class="rank-text">
<text
x="${rank.level.length === 1 ? "-4" : "0"}"
y="0"
alignment-baseline="central"
dominant-baseline="central"
text-anchor="middle"
>
${rank.level}
</text>
</g>
</g>`;

return card.render(`
${rankCircle}

Expand Down
16 changes: 16 additions & 0 deletions tests/renderStatsCard.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "rank-circle")).not.toBeInTheDocument();
});

it("should render with custom width set", () => {
document.body.innerHTML = renderStatsCard(stats);
expect(document.querySelector("svg")).toHaveAttribute("width", "495");

document.body.innerHTML = renderStatsCard(stats, { card_width: 400 });
expect(document.querySelector("svg")).toHaveAttribute("width", "400");
});

it("should render with custom width set and limit minimum width", () => {
document.body.innerHTML = renderStatsCard(stats, { card_width: 1 });
expect(document.querySelector("svg")).toHaveAttribute("width", "340");

document.body.innerHTML = renderStatsCard(stats, { card_width: 1, hide_rank: true });
rickstaa marked this conversation as resolved.
Show resolved Hide resolved
expect(document.querySelector("svg")).toHaveAttribute("width", "305.81250000000006");
});

it("should render default colors properly", () => {
document.body.innerHTML = renderStatsCard(stats);

Expand Down