diff --git a/api/index.js b/api/index.js index 66c119a5e0563..52bc2c0e39ffe 100644 --- a/api/index.js +++ b/api/index.js @@ -18,6 +18,7 @@ export default async (req, res) => { hide_title, hide_border, card_width, + card_height, hide_rank, show_icons, include_all_commits, @@ -123,6 +124,7 @@ export default async (req, res) => { hide_title: parseBoolean(hide_title), hide_border: parseBoolean(hide_border), card_width: parseInt(card_width, 10), + card_height: parseInt(card_height, 10), hide_rank: parseBoolean(hide_rank), include_all_commits: parseBoolean(include_all_commits), commits_year: parseInt(commits_year, 10), diff --git a/readme.md b/readme.md index 12256703b0a3d..f3d8cd081a696 100644 --- a/readme.md +++ b/readme.md @@ -125,6 +125,14 @@ Change the `?username=` value to your GitHub username. > [!NOTE]\ > Available ranks are S (top 1%), A+ (12.5%), A (25%), A- (37.5%), B+ (50%), B (62.5%), B- (75%), C+ (87.5%) and C (everyone). This ranking scheme is based on the [Japanese academic grading](https://wikipedia.org/wiki/Academic_grading_in_Japan) system. The global percentile is calculated as a weighted sum of percentiles for each statistic (number of commits, pull requests, reviews, issues, stars, and followers), based on the cumulative distribution function of the [exponential](https://wikipedia.org/wiki/exponential_distribution) and the [log-normal](https://wikipedia.org/wiki/Log-normal_distribution) distributions. The implementation can be investigated at [src/calculateRank.js](https://github.com/anuraghazra/github-readme-stats/blob/master/src/calculateRank.js). The circle around the rank shows 100 minus the global percentile. +### Adjusting card dimensions + +You can customize the width and height of the stats card using the `card_width` and `card_height` parameters to better fit your layout: + +```md +![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&card_width=600&card_height=300) +``` + ### Hiding individual stats You can pass a query parameter `&hide=` to hide any specific stats with comma-separated values. @@ -371,6 +379,7 @@ If we don't support your language, please consider contributing! You can find mo | `hide` | Hides the [specified items](#hiding-individual-stats) from stats. | string (comma-separated values) | `null` | | `hide_title` | Hides the title of your stats card. | boolean | `false` | | `card_width` | Sets the card's width manually. | number | `500px (approx.)` | +| `card_height` | Sets the card's height manually. | number | `195px (approx.)` | | `hide_rank` | Hides the rank and automatically resizes the card width. | boolean | `false` | | `rank_icon` | Shows alternative rank icon (i.e. `github`, `percentile` or `default`). | enum | `default` | | `show_icons` | Shows icons near all stats. | boolean | `false` | @@ -386,7 +395,7 @@ If we don't support your language, please consider contributing! You can find mo | `commits_year` | Filters and counts only commits made in the specified year. | integer _(YYYY)_ | ` (one year to date)` | > [!NOTE]\ -> When hide\_rank=`true`, the minimum card width is 270 px + the title length and padding. +> When hide\_rank=`true`, the minimum card width is 270 px + the title length and padding. When hide\_rank=`false`, the minimum card height is 150 px to accommodate the rank circle. *** @@ -714,6 +723,10 @@ Choose from any of the [default themes](#themes) ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra\&show_icons=true\&title_color=fff\&icon_color=79ff97\&text_color=9f9f9f\&bg_color=151515) +* Customizing card dimensions + +![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra\&card_width=600\&card_height=300) + * Setting card locale ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api/?username=anuraghazra\&locale=es) diff --git a/src/cards/stats.js b/src/cards/stats.js index 3e853b0a41274..848cfe321452a 100644 --- a/src/cards/stats.js +++ b/src/cards/stats.js @@ -235,6 +235,7 @@ const renderStatsCard = (stats, options = {}) => { hide_title = false, hide_border = false, card_width, + card_height, hide_rank = false, include_all_commits = false, commits_year, @@ -414,10 +415,21 @@ const renderStatsCard = (stats, options = {}) => { // Calculate the card height depending on how many items there are // but if rank circle is visible clamp the minimum height to `150` - let height = Math.max( - 45 + (statItems.length + 1) * lheight, - hide_rank ? 0 : statItems.length ? 150 : 180, - ); + // Allow custom height to override automatic calculation + let height = card_height + ? isNaN(card_height) + ? Math.max( + 45 + (statItems.length + 1) * lheight, + hide_rank ? 0 : statItems.length ? 150 : 180, + ) + : Math.max( + card_height, + hide_rank ? 45 + (statItems.length + 1) * lheight : 150, + ) + : Math.max( + 45 + (statItems.length + 1) * lheight, + hide_rank ? 0 : statItems.length ? 150 : 180, + ); // the lower the user's percentile the better const progress = 100 - rank.percentile; diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index 94f36adc624b7..7ca4863d293d0 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -18,6 +18,7 @@ export type StatCardOptions = CommonOptions & { show_icons: boolean; hide_title: boolean; card_width: number; + card_height: number; hide_rank: boolean; include_all_commits: boolean; commits_year: number; diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index a460454052506..549ef76a60789 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -179,6 +179,27 @@ describe("Test renderStatsCard", () => { expect(document.querySelector("svg")).toHaveAttribute("width", "420"); }); + it("should render with custom height set", () => { + document.body.innerHTML = renderStatsCard(stats); + expect(document.querySelector("svg")).toHaveAttribute("height", "195"); + + document.body.innerHTML = renderStatsCard(stats, { card_height: 250 }); + expect(document.querySelector("svg")).toHaveAttribute("height", "250"); + }); + + it("should render with custom height set and respect minimum height", () => { + // Test that very small heights are clamped to minimum + document.body.innerHTML = renderStatsCard(stats, { card_height: 50 }); + expect(document.querySelector("svg")).toHaveAttribute("height", "150"); + + // Test minimum height when rank is hidden + document.body.innerHTML = renderStatsCard(stats, { + card_height: 50, + hide_rank: true, + }); + expect(document.querySelector("svg")).toHaveAttribute("height", "195"); // Should use calculated minimum for content + }); + it("should render default colors properly", () => { document.body.innerHTML = renderStatsCard(stats);