Repository: anuraghazra/github-readme-stats
Pull request #2460 (2023-01-24 13:26:20)

fix: fixes card overflow problem #2452
This PR makes sure that the card width is formatted correctly. See #2452 for more information on the current incorrect behavoir.


codecov[bot]: # [Codecov](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2460?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) Report
Base: **96.90**% // Head: **96.91**% // Increases project coverage by **`+0.01%`** :tada:
> Coverage data is based on head [(`29e6d58`)](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2460?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) compared to base [(`4b17300`)](https://codecov.io/gh/anuraghazra/github-readme-stats/commit/4b173001264e9774a2179915519e6129af689625?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #2460      +/-   ##
==========================================
+ Coverage   96.90%   96.91%   +0.01%     
==========================================
  Files          22       22              
  Lines        3882     3896      +14     
  Branches      337      337              
==========================================
+ Hits         3762     3776      +14     
  Misses        118      118              
  Partials        2        2              
```


| [Impacted Files](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) | Coverage Δ | |
|---|---|---|
| [src/cards/stats-card.js](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra#diff-c3JjL2NhcmRzL3N0YXRzLWNhcmQuanM=) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2460?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra).


Patch:
diff --git a/.github/workflows/deploy-prep.py b/.github/workflows/deploy-prep.py
new file mode 100644
index 0000000..794c19a
--- /dev/null
+++ b/.github/workflows/deploy-prep.py
@@ -0,0 +1,10 @@
+import os
+
+file = open('./vercel.json', 'r')
+str = file.read()
+file = open('./vercel.json', 'w')
+
+str = str.replace('"maxDuration": 10', '"maxDuration": 30')
+
+file.write(str)
+file.close()
diff --git a/.github/workflows/deploy-prep.yml b/.github/workflows/deploy-prep.yml
new file mode 100644
index 0000000..0626e13
--- /dev/null
+++ b/.github/workflows/deploy-prep.yml
@@ -0,0 +1,20 @@
+name: Deployment Prep
+on:
+  workflow_dispatch:
+  push:
+    branches:
+      - master
+
+jobs:
+  config:
+    if: github.repository == 'anuraghazra/github-readme-stats'
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Deployment Prep
+        run: python ./.github/workflows/deploy-prep.py
+      - uses: stefanzweifel/git-auto-commit-action@v4
+        with:
+          branch: vercel
+          create_branch: true
+          push_options: "--force"
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index a049ecc..f39a968 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -12,6 +12,11 @@ import {
 import { getStyles } from "../getStyles.js";
 import { statCardLocales } from "../translations.js";
 
+const CARD_MIN_WIDTH = 287;
+const CARD_DEFAULT_WIDTH = 287;
+const RANK_CARD_MIN_WIDTH = 420;
+const RANK_CARD_DEFAULT_WIDTH = 450;
+
 /**
  * Create a stats card text item.
  *
@@ -218,11 +223,17 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
     When hide_rank=false, the minimum card_width is 340 px + the icon width (if show_icons=true).
     Numbers are picked by looking at existing dimensions on production.
   */
-  const iconWidth = show_icons ? 16 : 0;
-  const minCardWidth = hide_rank
-    ? clampValue(50 /* padding */ + calculateTextWidth() * 2, 270, Infinity)
-    : 340 + iconWidth;
-  const defaultCardWidth = hide_rank ? 270 : 495;
+  const iconWidth = show_icons ? 16 + /* padding */ 1 : 0;
+  const minCardWidth =
+    (hide_rank
+      ? clampValue(
+          50 /* padding */ + calculateTextWidth() * 2,
+          CARD_MIN_WIDTH,
+          Infinity,
+        )
+      : RANK_CARD_MIN_WIDTH) + iconWidth;
+  const defaultCardWidth =
+    (hide_rank ? CARD_DEFAULT_WIDTH : RANK_CARD_DEFAULT_WIDTH) + iconWidth;
   let width = isNaN(card_width) ? defaultCardWidth : card_width;
   if (width < minCardWidth) {
     width = minCardWidth;
@@ -251,18 +262,21 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
 
   /**
    * Calculates the right rank circle translation values such that the rank circle
-   * keeps respecting the padding.
+   * keeps respecting the following padding:
    *
-   * width > 450: The default left padding of 50 px will be used.
-   * width < 450: The left and right padding will shrink equally.
+   * width > RANK_CARD_DEFAULT_WIDTH: The default right padding of 70 px will be used.
+   * width < RANK_CARD_DEFAULT_WIDTH: The left and right padding will be enlarged
+   *   equally from a certain minimum at RANK_CARD_MIN_WIDTH.
    *
    * @returns {number} - Rank circle translation value.
    */
   const calculateRankXTranslation = () => {
-    if (width < 450) {
-      return width - 95 + (45 * (450 - 340)) / 110;
+    const minXTranslation = RANK_CARD_MIN_WIDTH + iconWidth - 70;
+    if (width > RANK_CARD_DEFAULT_WIDTH) {
+      const xMaxExpansion = minXTranslation + (450 - minCardWidth) / 2;
+      return xMaxExpansion + width - RANK_CARD_DEFAULT_WIDTH;
     } else {
-      return width - 95;
+      return minXTranslation + (width - minCardWidth) / 2;
     }
   };
 
diff --git a/vercel.json b/vercel.json
index aee61ce..ddf82eb 100644
--- a/vercel.json
+++ b/vercel.json
@@ -2,7 +2,7 @@
   "functions": {
     "api/*.js": {
       "memory": 128,
-      "maxDuration": 30
+      "maxDuration": 10
     }
   },
   "redirects": [


Test patch:
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 5afb1f0..748b7a3 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -78,16 +78,17 @@ describe("Test renderStatsCard", () => {
 
   it("should render with custom width set", () => {
     document.body.innerHTML = renderStatsCard(stats);
-    expect(document.querySelector("svg")).toHaveAttribute("width", "495");
+    expect(document.querySelector("svg")).toHaveAttribute("width", "450");
 
-    document.body.innerHTML = renderStatsCard(stats, { card_width: 400 });
-    expect(document.querySelector("svg")).toHaveAttribute("width", "400");
+    document.body.innerHTML = renderStatsCard(stats, { card_width: 500 });
+    expect(document.querySelector("svg")).toHaveAttribute("width", "500");
   });
 
   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");
+    expect(document.querySelector("svg")).toHaveAttribute("width", "420");
 
+    // Test default minimum card width without rank circle.
     document.body.innerHTML = renderStatsCard(stats, {
       card_width: 1,
       hide_rank: true,
@@ -97,6 +98,7 @@ describe("Test renderStatsCard", () => {
       "305.81250000000006",
     );
 
+    // Test minimum card width with rank and icons.
     document.body.innerHTML = renderStatsCard(stats, {
       card_width: 1,
       hide_rank: true,
@@ -104,22 +106,24 @@ describe("Test renderStatsCard", () => {
     });
     expect(document.querySelector("svg")).toHaveAttribute(
       "width",
-      "305.81250000000006",
+      "322.81250000000006",
     );
 
+    // Test minimum card width with icons but without rank.
     document.body.innerHTML = renderStatsCard(stats, {
       card_width: 1,
       hide_rank: false,
       show_icons: true,
     });
-    expect(document.querySelector("svg")).toHaveAttribute("width", "356");
+    expect(document.querySelector("svg")).toHaveAttribute("width", "437");
 
+    // Test minimum card width without icons or rank.
     document.body.innerHTML = renderStatsCard(stats, {
       card_width: 1,
       hide_rank: false,
       show_icons: false,
     });
-    expect(document.querySelector("svg")).toHaveAttribute("width", "340");
+    expect(document.querySelector("svg")).toHaveAttribute("width", "420");
   });
 
   it("should render default colors properly", () => {
@@ -312,7 +316,7 @@ describe("Test renderStatsCard", () => {
 
     expect(
       document.body.getElementsByTagName("svg")[0].getAttribute("width"),
-    ).toBe("270");
+    ).toBe("287");
   });
 
   it("should render translations", () => {