Repository: anuraghazra/github-readme-stats
Pull request #3361 (2023-10-14 19:53:00)

docs(translations): remove broken sponsors links

vercel[bot]: [vc]: #A4rGf2sGsopcAJSIyNZYAt1020G+29OfyIOANXtVX9k=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJnaXRodWItcmVhZG1lLXN0YXRzIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2dpdGh1Yi1yZWFkbWUtc3RhdHMtdGVhbS9naXRodWItcmVhZG1lLXN0YXRzL0NYM2RzUzl5TmluTWltRXhoTVY0aFpTYTZqVmsiLCJwcmV2aWV3VXJsIjoiZ2l0aHViLXJlYWRtZS1zdGF0cy1naXQtZG9jc3RyYS04MGY1MTUtZ2l0aHViLXJlYWRtZS1zdGF0cy10ZWFtLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiUEVORElORyJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **github-readme-stats** | 🔄 Building ([Inspect](https://vercel.com/github-readme-stats-team/github-readme-stats/CX3dsS9yNinMimExhMV4hZSa6jVk)) | [Visit Preview](https://github-readme-stats-git-docstra-80f515-github-readme-stats-team.vercel.app) | Oct 14, 2023 7:53pm |


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3361?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) Report
All modified lines are covered by tests :white_check_mark:
> Comparison is base [(`4fd52e6`)](https://app.codecov.io/gh/anuraghazra/github-readme-stats/commit/4fd52e6f64a579514e743ff2e7f7c9000075ed45?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) 98.39% compared to head [(`52f37b1`)](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3361?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) 98.39%.

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


```diff
@@           Coverage Diff           @@
##           master    #3361   +/-   ##
=======================================
  Coverage   98.39%   98.39%           
=======================================
  Files          27       27           
  Lines        5979     5979           
  Branches      533      533           
=======================================
  Hits         5883     5883           
  Misses         93       93           
  Partials        3        3           
```




</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3361?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra).   
:loudspeaker: Have feedback on the report? [Share it here](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/.eslintrc.json b/.eslintrc.json
index 0236a06..9ec7f29 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -195,7 +195,7 @@
         // "no-lonely-if": "warn",
         "no-mixed-spaces-and-tabs": "warn",
         "no-multiple-empty-lines": "warn",
-        // "no-negated-condition": "off",
+        "no-negated-condition": "warn",
         // "no-nested-ternary": "warn",
         // "no-new-object": "warn",
         // "no-plusplus": "off",
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8fdbf1f..d2244a1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -58,6 +58,12 @@ GitHub Readme Stats supports custom theming, and you can also contribute new the
 
 To contribute your theme you need to edit the [themes/index.js](./themes/index.js) file and add it at the end of the file.
 
+## Translations Contribution
+
+GitHub Readme Stats supports multiple languages, if we are missing your language, you can contribute it! You can check the currently supported languages [here](./readme.md#available-locales).
+
+To contribute your language you need to edit the [src/translations.js](./src/translations.js) file and add new property to each object where the key is the language code in [ISO 639-1 standard](https://www.andiamo.co.uk/resources/iso-language-codes/) and the value is the translated string.
+
 ## Any contributions you make will be under the MIT Software License
 
 In short, when you submit changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
diff --git a/docs/readme_cn.md b/docs/readme_cn.md
index f33f98d..0773656 100644
--- a/docs/readme_cn.md
+++ b/docs/readme_cn.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_de.md b/docs/readme_de.md
index b1c43f0..98e5adc 100644
--- a/docs/readme_de.md
+++ b/docs/readme_de.md
@@ -25,12 +25,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_es.md b/docs/readme_es.md
index b49f5f7..9444cda 100644
--- a/docs/readme_es.md
+++ b/docs/readme_es.md
@@ -25,12 +25,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Apoyado%20por-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Apoyado%20por-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_fr.md b/docs/readme_fr.md
index 4d58663..0f035f9 100644
--- a/docs/readme_fr.md
+++ b/docs/readme_fr.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supporté%20par-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supporté%20par-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_it.md b/docs/readme_it.md
index aed9ced..8f16f4e 100644
--- a/docs/readme_it.md
+++ b/docs/readme_it.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supportato%20da-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supportato%20da-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_ja.md b/docs/readme_ja.md
index 24d66cd..d338785 100644
--- a/docs/readme_ja.md
+++ b/docs/readme_ja.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_kr.md b/docs/readme_kr.md
index d3b9f48..eaddc59 100644
--- a/docs/readme_kr.md
+++ b/docs/readme_kr.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_nl.md b/docs/readme_nl.md
index 2279b66..a2edf14 100644
--- a/docs/readme_nl.md
+++ b/docs/readme_nl.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_np.md b/docs/readme_np.md
index 4537e6e..788c991 100644
--- a/docs/readme_np.md
+++ b/docs/readme_np.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_pt-BR.md b/docs/readme_pt-BR.md
index ea123c6..37707dd 100644
--- a/docs/readme_pt-BR.md
+++ b/docs/readme_pt-BR.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Apoiado%20por-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Apoiado%20por-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/docs/readme_tr.md b/docs/readme_tr.md
index bed1ca4..16b2f06 100644
--- a/docs/readme_tr.md
+++ b/docs/readme_tr.md
@@ -24,12 +24,6 @@
     </a>
     <br />
     <br />
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=1227">
-      <img src="https://img.shields.io/badge/Supported%20by-VSCode%20Power%20User%20%E2%86%92-gray.svg?colorA=655BE1&colorB=4F44D6&style=for-the-badge"/>
-    </a>
-    <a href="https://a.paddle.com/v2/click/16413/119403?link=2345">
-      <img src="https://img.shields.io/badge/Supported%20by-Node%20Cli.com%20%E2%86%92-gray.svg?colorA=61c265&colorB=4CAF50&style=for-the-badge"/>
-    </a>
   </p>
 
   <p align="center">
diff --git a/readme.md b/readme.md
index 5015e14..ff826b3 100644
--- a/readme.md
+++ b/readme.md
@@ -24,6 +24,9 @@
     </a>
     <br />
     <br />
+    <a href="https://vercel.com?utm\_source=github\_readme\_stats\_team\&utm\_campaign=oss">
+      <img src="./powered-by-vercel.svg"/>
+    </a>
   </p>
 
   <p align="center">
@@ -118,13 +121,16 @@ Please visit [this link](https://give.do/fundraisers/stand-beside-the-victims-of
   - [Keep your fork up to date](#keep-your-fork-up-to-date)
 - [:sparkling\_heart: Support the project](#sparkling_heart-support-the-project)
 
-# Important Notice <!-- omit in toc -->
+# Important Notices <!-- omit in toc -->
 
 > [!IMPORTANT]\
 > Since the GitHub API only [allows 5k requests per hour per user account](https://docs.github.com/en/graphql/overview/resource-limitations), the public Vercel instance hosted on `https://github-readme-stats.vercel.app/api` could possibly hit the rate limiter (see [#1471](https://github.com/anuraghazra/github-readme-stats/issues/1471)). We use caching to prevent this from happening (see https://github.com/anuraghazra/github-readme-stats#common-options). You can turn off these rate limit protections by deploying [your own Vercel instance](#disable-rate-limit-protections).
 
 <img alt="Uptime Badge" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fgithub-readme-stats-git-monitoring-github-readme-stats-team.vercel.app%2Fapi%2Fstatus%2Fup%3Ftype%3Dshields">
 
+> [!IMPORTANT]\
+> We're a small team, and to prioritize, we rely on upvotes :+1:. We use Top issues dashboard for tracking community demand (see [#1935](https://github.com/anuraghazra/github-readme-stats/issues/1935)). Do not hesitate to upvote the issues and pull requests you are interested in. We will work on the most upvoted first.
+
 # GitHub Stats Card
 
 Copy-paste this into your markdown content, and that is it. Simple!
diff --git a/scripts/close-stale-theme-prs.js b/scripts/close-stale-theme-prs.js
index 3b513f1..4f2c936 100644
--- a/scripts/close-stale-theme-prs.js
+++ b/scripts/close-stale-theme-prs.js
@@ -155,7 +155,9 @@ const run = async () => {
     // Loop through all stale invalid theme pull requests and close them.
     for (const prNumber of staleThemePRsNumbers) {
       debug(`Closing #${prNumber} because it is stale...`);
-      if (!dryRun) {
+      if (dryRun) {
+        debug("Dry run enabled, skipping...");
+      } else {
         await octokit.rest.issues.createComment({
           owner,
           repo,
@@ -168,8 +170,6 @@ const run = async () => {
           pull_number: prNumber,
           state: "closed",
         });
-      } else {
-        debug("Dry run enabled, skipping...");
       }
     }
   } catch (error) {
diff --git a/scripts/generate-theme-doc.js b/scripts/generate-theme-doc.js
index 2d2458e..524ddec 100644
--- a/scripts/generate-theme-doc.js
+++ b/scripts/generate-theme-doc.js
@@ -22,7 +22,7 @@ Use \`?theme=THEME_NAME\` parameter like so:
 
 ## Stats
 
-> These themes work both for the Stats Card and Repo Card.
+> These themes works with all five our cards: Stats Card, Repo Card, Gist Card, Top languages Card and Wakatime Card.
 
 | | | |
 | :--: | :--: | :--: |
@@ -30,7 +30,7 @@ ${STAT_CARD_TABLE_FLAG}
 
 ## Repo Card
 
-> These themes work both for the Stats Card and Repo Card.
+> These themes works with all five our cards: Stats Card, Repo Card, Gist Card, Top languages Card and Wakatime Card.
 
 | | | |
 | :--: | :--: | :--: |
@@ -69,7 +69,7 @@ const createTableItem = ({ link, label, isRepoCard }) => {
 const generateTable = ({ isRepoCard }) => {
   const rows = [];
   const themesFiltered = Object.keys(themes).filter(
-    (name) => name !== (!isRepoCard ? "default_repocard" : "default"),
+    (name) => name !== (isRepoCard ? "default" : "default_repocard"),
   );
 
   for (let i = 0; i < themesFiltered.length; i += 3) {
diff --git a/scripts/preview-theme.js b/scripts/preview-theme.js
index fd55d57..65f37a4 100644
--- a/scripts/preview-theme.js
+++ b/scripts/preview-theme.js
@@ -172,18 +172,18 @@ const upsertComment = async (
   body,
 ) => {
   let resp;
-  if (commentId !== undefined) {
-    resp = await octokit.rest.issues.updateComment({
+  if (commentId === undefined) {
+    resp = await octokit.rest.issues.createComment({
       owner,
       repo,
-      comment_id: commentId,
+      issue_number: issueNumber,
       body,
     });
   } else {
-    resp = await octokit.rest.issues.createComment({
+    resp = await octokit.rest.issues.updateComment({
       owner,
       repo,
-      issue_number: issueNumber,
+      comment_id: commentId,
       body,
     });
   }
@@ -341,10 +341,10 @@ const parseJSON = (json) => {
       .filter((x) => typeof x !== "string" || !!x.trim()); // Split json into array of strings and objects.
     if (splitJson[0].replace(/\s+/g, "") === "},") {
       splitJson[0] = "},";
-      if (!/\s*}\s*,?\s*$/.test(splitJson[1])) {
-        splitJson.push(splitJson.shift());
-      } else {
+      if (/\s*}\s*,?\s*$/.test(splitJson[1])) {
         splitJson.shift();
+      } else {
+        splitJson.push(splitJson.shift());
       }
       parsedJson = splitJson.join("");
     }
@@ -466,10 +466,7 @@ export const run = async () => {
       // Check if the theme colors are valid.
       debug("Theme preview body: Check if the theme colors are valid...");
       let invalidColors = false;
-      if (!colors) {
-        warnings.push("Theme colors are missing");
-        invalidColors = true;
-      } else {
+      if (colors) {
         const missingKeys = REQUIRED_COLOR_PROPS.filter(
           (x) => !Object.keys(colors).includes(x),
         );
@@ -507,6 +504,9 @@ export const run = async () => {
             }
           }
         }
+      } else {
+        warnings.push("Theme colors are missing");
+        invalidColors = true;
       }
       if (invalidColors) {
         themeValid[theme] = false;
@@ -597,7 +597,10 @@ export const run = async () => {
     // Create or update theme-preview comment.
     debug("Create or update theme-preview comment...");
     let comment_url;
-    if (!DRY_RUN) {
+    if (DRY_RUN) {
+      info(`DRY_RUN: Comment body: ${commentBody}`);
+      comment_url = "";
+    } else {
       comment_url = await upsertComment(
         OCTOKIT,
         PULL_REQUEST_ID,
@@ -606,9 +609,6 @@ export const run = async () => {
         comment?.id,
         commentBody,
       );
-    } else {
-      info(`DRY_RUN: Comment body: ${commentBody}`);
-      comment_url = "";
     }
 
     // Change review state and add/remove `invalid` label based on theme PR validity.
@@ -620,7 +620,10 @@ export const run = async () => {
     const reviewReason = themesValid
       ? undefined
       : INVALID_REVIEW_COMMENT(comment_url);
-    if (!DRY_RUN) {
+    if (DRY_RUN) {
+      info(`DRY_RUN: Review state: ${reviewState}`);
+      info(`DRY_RUN: Review reason: ${reviewReason}`);
+    } else {
       await addReview(
         OCTOKIT,
         PULL_REQUEST_ID,
@@ -637,13 +640,13 @@ export const run = async () => {
         "invalid",
         !themesValid,
       );
-    } else {
-      info(`DRY_RUN: Review state: ${reviewState}`);
-      info(`DRY_RUN: Review reason: ${reviewReason}`);
     }
   } catch (error) {
     debug("Set review state to `REQUEST_CHANGES` and add `invalid` label...");
-    if (!DRY_RUN) {
+    if (DRY_RUN) {
+      info(`DRY_RUN: Review state: REQUEST_CHANGES`);
+      info(`DRY_RUN: Review reason: ${error.message}`);
+    } else {
       await addReview(
         OCTOKIT,
         PULL_REQUEST_ID,
@@ -662,9 +665,6 @@ export const run = async () => {
         "invalid",
         true,
       );
-    } else {
-      info(`DRY_RUN: Review state: REQUEST_CHANGES`);
-      info(`DRY_RUN: Review reason: ${error.message}`);
     }
     setFailed(error.message);
   }
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index dad81bb..5f57205 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -10,7 +10,6 @@ import {
   kFormatter,
   measureText,
 } from "../common/utils.js";
-import { getStyles } from "../getStyles.js";
 import { statCardLocales } from "../translations.js";
 
 const CARD_MIN_WIDTH = 287;
@@ -76,6 +75,118 @@ const createTextNode = ({
   `;
 };
 
+/**
+ * Calculates progress along the boundary of the circle i.e it's circumference.
+ *
+ * @param {number} value The rank value to calculate progress for.
+ * @returns {number} Progress value.
+ */
+const calculateCircleProgress = (value) => {
+  const radius = 40;
+  const c = Math.PI * (radius * 2);
+
+  if (value < 0) {
+    value = 0;
+  }
+  if (value > 100) {
+    value = 100;
+  }
+
+  return ((100 - value) / 100) * c;
+};
+
+/**
+ * Retrieves the animation to display progress along the circumference of circle
+ * from the beginning to the given value in a clockwise direction.
+ *
+ * @param {{progress: number}} progress The progress value to animate to.
+ * @returns {string} Progress animation css.
+ */
+const getProgressAnimation = ({ progress }) => {
+  return `
+    @keyframes rankAnimation {
+      from {
+        stroke-dashoffset: ${calculateCircleProgress(0)};
+      }
+      to {
+        stroke-dashoffset: ${calculateCircleProgress(progress)};
+      }
+    }
+  `;
+};
+
+/**
+ * Retrieves CSS styles for a card.
+ *
+ * @param {Object} colors The colors to use for the card.
+ * @param {string} colors.titleColor The title color.
+ * @param {string} colors.textColor The text color.
+ * @param {string} colors.iconColor The icon color.
+ * @param {string} colors.ringColor The ring color.
+ * @param {boolean} colors.show_icons Whether to show icons.
+ * @param {number} colors.progress The progress value to animate to.
+ * @returns {string} Card CSS styles.
+ */
+const getStyles = ({
+  // eslint-disable-next-line no-unused-vars
+  titleColor,
+  textColor,
+  iconColor,
+  ringColor,
+  show_icons,
+  progress,
+}) => {
+  return `
+    .stat {
+      font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
+    }
+    @supports(-moz-appearance: auto) {
+      /* Selector detects Firefox */
+      .stat { font-size:12px; }
+    }
+    .stagger {
+      opacity: 0;
+      animation: fadeInAnimation 0.3s ease-in-out forwards;
+    }
+    .rank-text {
+      font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
+      animation: scaleInAnimation 0.3s ease-in-out forwards;
+    }
+    .rank-percentile-header {
+      font-size: 14px;
+    }
+    .rank-percentile-text {
+      font-size: 16px;
+    }
+    
+    .not_bold { font-weight: 400 }
+    .bold { font-weight: 700 }
+    .icon {
+      fill: ${iconColor};
+      display: ${show_icons ? "block" : "none"};
+    }
+
+    .rank-circle-rim {
+      stroke: ${ringColor};
+      fill: none;
+      stroke-width: 6;
+      opacity: 0.2;
+    }
+    .rank-circle {
+      stroke: ${ringColor};
+      stroke-dasharray: 250;
+      fill: none;
+      stroke-width: 6;
+      stroke-linecap: round;
+      opacity: 0.8;
+      transform-origin: -10px 8px;
+      transform: rotate(-90deg);
+      animation: rankAnimation 1s forwards ease-in-out;
+    }
+    ${process.env.NODE_ENV === "test" ? "" : getProgressAnimation({ progress })}
+  `;
+};
+
 /**
  * @typedef {import('../fetchers/types').StatsData} StatsData
  * @typedef {import('./types').StatCardOptions} StatCardOptions
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 9593f98..758bd34 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -383,14 +383,14 @@ const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
 
   return `
   ${
-    !hideProgress
-      ? `
-  <mask id="rect-mask">
-      <rect x="0" y="0" width="${offsetWidth}" height="8" fill="white" rx="5"/>
-    </mask>
-    ${compactProgressBar}
-  `
-      : ""
+    hideProgress
+      ? ""
+      : `
+      <mask id="rect-mask">
+          <rect x="0" y="0" width="${offsetWidth}" height="8" fill="white" rx="5"/>
+        </mask>
+        ${compactProgressBar}
+      `
   }
     <g transform="translate(0, ${hideProgress ? "0" : "25"})">
       ${createLanguageTextNode({
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index 187af7e..a6a203d 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -8,7 +8,6 @@ import {
   getCardColors,
   lowercaseTrim,
 } from "../common/utils.js";
-import { getStyles } from "../getStyles.js";
 import { wakatimeCardLocales } from "../translations.js";
 
 /** Import language colors.
@@ -158,6 +157,36 @@ const recalculatePercentages = (languages) => {
   });
 };
 
+/**
+ * Retrieves CSS styles for a card.
+ *
+ * @param {Object} colors The colors to use for the card.
+ * @param {string} colors.titleColor The title color.
+ * @param {string} colors.textColor The text color.
+ * @returns {string} Card CSS styles.
+ */
+const getStyles = ({
+  // eslint-disable-next-line no-unused-vars
+  titleColor,
+  textColor,
+}) => {
+  return `
+    .stat {
+      font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
+    }
+    @supports(-moz-appearance: auto) {
+      /* Selector detects Firefox */
+      .stat { font-size:12px; }
+    }
+    .stagger {
+      opacity: 0;
+      animation: fadeInAnimation 0.3s ease-in-out forwards;
+    }
+    .not_bold { font-weight: 400 }
+    .bold { font-weight: 700 }
+  `;
+};
+
 /**
  * @typedef {import('../fetchers/types').WakaTimeData} WakaTimeData
  * @typedef {import('./types').WakaTimeOptions} WakaTimeOptions
@@ -235,7 +264,6 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
   const cssStyles = getStyles({
     titleColor,
     textColor,
-    iconColor,
   });
 
   let finalLayout = "";
@@ -287,11 +315,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
           : noCodingActivityNode({
               // @ts-ignore
               color: textColor,
-              text: !stats.is_coding_activity_visible
-                ? i18n.t("wakatimecard.notpublic")
-                : stats.is_other_usage_visible
-                ? i18n.t("wakatimecard.nocodingactivity")
-                : i18n.t("wakatimecard.nocodedetails"),
+              text: stats.is_coding_activity_visible
+                ? stats.is_other_usage_visible
+                  ? i18n.t("wakatimecard.nocodingactivity")
+                  : i18n.t("wakatimecard.nocodedetails")
+                : i18n.t("wakatimecard.notpublic"),
             })
       }
     `;
@@ -316,11 +344,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
             noCodingActivityNode({
               // @ts-ignore
               color: textColor,
-              text: !stats.is_coding_activity_visible
-                ? i18n.t("wakatimecard.notpublic")
-                : stats.is_other_usage_visible
-                ? i18n.t("wakatimecard.nocodingactivity")
-                : i18n.t("wakatimecard.nocodedetails"),
+              text: stats.is_coding_activity_visible
+                ? stats.is_other_usage_visible
+                  ? i18n.t("wakatimecard.nocodingactivity")
+                  : i18n.t("wakatimecard.nocodedetails")
+                : i18n.t("wakatimecard.notpublic"),
             }),
           ],
       gap: lheight,
diff --git a/src/common/Card.js b/src/common/Card.js
index 33e6bb9..d32da56 100644
--- a/src/common/Card.js
+++ b/src/common/Card.js
@@ -1,4 +1,3 @@
-import { getAnimations } from "../getStyles.js";
 import { encodeHTML, flexLayout } from "./utils.js";
 
 class Card {
@@ -40,9 +39,9 @@ class Card {
     // returns theme based colors with proper overrides and defaults
     this.colors = colors;
     this.title =
-      customTitle !== undefined
-        ? encodeHTML(customTitle)
-        : encodeHTML(defaultTitle);
+      customTitle === undefined
+        ? encodeHTML(defaultTitle)
+        : encodeHTML(customTitle);
 
     this.css = "";
 
@@ -173,6 +172,33 @@ class Card {
       : "";
   }
 
+  /**
+   * Retrieves css animations for a card.
+   *
+   * @returns {string} Animation css.
+   */
+  getAnimations = () => {
+    return `
+      /* Animations */
+      @keyframes scaleInAnimation {
+        from {
+          transform: translate(-5px, 5px) scale(0);
+        }
+        to {
+          transform: translate(-5px, 5px) scale(1);
+        }
+      }
+      @keyframes fadeInAnimation {
+        from {
+          opacity: 0;
+        }
+        to {
+          opacity: 1;
+        }
+      }
+    `;
+  };
+
   /**
    * @param {string} body The inner body of the card.
    * @returns {string} The rendered card.
@@ -202,7 +228,7 @@ class Card {
           }
           ${this.css}
 
-          ${process.env.NODE_ENV === "test" ? "" : getAnimations()}
+          ${process.env.NODE_ENV === "test" ? "" : this.getAnimations()}
           ${
             this.animations === false
               ? `* { animation-duration: 0s !important; animation-delay: 0s !important; }`
diff --git a/src/common/utils.js b/src/common/utils.js
index 95d683c..4fb473e 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -415,7 +415,7 @@ const wrapTextMultiline = (text, width = 59, maxLines = 3) => {
 const noop = () => {};
 // return console instance based on the environment
 const logger =
-  process.env.NODE_ENV !== "test" ? console : { log: noop, error: noop };
+  process.env.NODE_ENV === "test" ? { log: noop, error: noop } : console;
 
 const ONE_MINUTE = 60;
 const FIVE_MINUTES = 300;
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index 1d6aebf..115cd50 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -89,7 +89,7 @@ const GRAPHQL_STATS_QUERY = `
  * @returns {Promise<AxiosResponse>} Axios response.
  */
 const fetcher = (variables, token) => {
-  const query = !variables.after ? GRAPHQL_STATS_QUERY : GRAPHQL_REPOS_QUERY;
+  const query = variables.after ? GRAPHQL_REPOS_QUERY : GRAPHQL_STATS_QUERY;
   return request(
     {
       query,
@@ -138,10 +138,10 @@ const statsFetcher = async ({
 
     // Store stats data.
     const repoNodes = res.data.data.user.repositories.nodes;
-    if (!stats) {
-      stats = res;
-    } else {
+    if (stats) {
       stats.data.data.user.repositories.nodes.push(...repoNodes);
+    } else {
+      stats = res;
     }
 
     // Disable multi page fetching on public Vercel instance due to rate limits.
diff --git a/src/getStyles.js b/src/getStyles.js
deleted file mode 100644
index c621ba1..0000000
--- a/src/getStyles.js
+++ /dev/null
@@ -1,142 +0,0 @@
-// @ts-check
-
-/**
- * Calculates progress along the boundary of the circle i.e it's circumference.
- *
- * @param {number} value The rank value to calculate progress for.
- * @returns {number} Progress value.
- */
-const calculateCircleProgress = (value) => {
-  const radius = 40;
-  const c = Math.PI * (radius * 2);
-
-  if (value < 0) {
-    value = 0;
-  }
-  if (value > 100) {
-    value = 100;
-  }
-
-  return ((100 - value) / 100) * c;
-};
-
-/**
- * Retrieves the animation to display progress along the circumference of circle
- * from the beginning to the given value in a clockwise direction.
- *
- * @param {{progress: number}} progress The progress value to animate to.
- * @returns {string} Progress animation css.
- */
-const getProgressAnimation = ({ progress }) => {
-  return `
-    @keyframes rankAnimation {
-      from {
-        stroke-dashoffset: ${calculateCircleProgress(0)};
-      }
-      to {
-        stroke-dashoffset: ${calculateCircleProgress(progress)};
-      }
-    }
-  `;
-};
-
-/**
- * Retrieves css animations for a card.
- *
- * @returns {string} Animation css.
- */
-const getAnimations = () => {
-  return `
-    /* Animations */
-    @keyframes scaleInAnimation {
-      from {
-        transform: translate(-5px, 5px) scale(0);
-      }
-      to {
-        transform: translate(-5px, 5px) scale(1);
-      }
-    }
-    @keyframes fadeInAnimation {
-      from {
-        opacity: 0;
-      }
-      to {
-        opacity: 1;
-      }
-    }
-  `;
-};
-
-/**
- * Retrieves CSS styles for a card.
- *
- * @param {Object} colors The colors to use for the card.
- * @param {string} colors.titleColor The title color.
- * @param {string} colors.textColor The text color.
- * @param {string} colors.iconColor The icon color.
- * @param {string} colors.ringColor The ring color.
- * @param {boolean} colors.show_icons Whether to show icons.
- * @param {number} colors.progress The progress value to animate to.
- * @returns {string} Card CSS styles.
- */
-const getStyles = ({
-  // eslint-disable-next-line no-unused-vars
-  titleColor,
-  textColor,
-  iconColor,
-  ringColor,
-  show_icons,
-  progress,
-}) => {
-  return `
-    .stat {
-      font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${textColor};
-    }
-    @supports(-moz-appearance: auto) {
-      /* Selector detects Firefox */
-      .stat { font-size:12px; }
-    }
-    .stagger {
-      opacity: 0;
-      animation: fadeInAnimation 0.3s ease-in-out forwards;
-    }
-    .rank-text {
-      font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor};
-      animation: scaleInAnimation 0.3s ease-in-out forwards;
-    }
-    .rank-percentile-header {
-      font-size: 14px;
-    }
-    .rank-percentile-text {
-      font-size: 16px;
-    }
-    
-    .not_bold { font-weight: 400 }
-    .bold { font-weight: 700 }
-    .icon {
-      fill: ${iconColor};
-      display: ${!!show_icons ? "block" : "none"};
-    }
-
-    .rank-circle-rim {
-      stroke: ${ringColor};
-      fill: none;
-      stroke-width: 6;
-      opacity: 0.2;
-    }
-    .rank-circle {
-      stroke: ${ringColor};
-      stroke-dasharray: 250;
-      fill: none;
-      stroke-width: 6;
-      stroke-linecap: round;
-      opacity: 0.8;
-      transform-origin: -10px 8px;
-      transform: rotate(-90deg);
-      animation: rankAnimation 1s forwards ease-in-out;
-    }
-    ${process.env.NODE_ENV === "test" ? "" : getProgressAnimation({ progress })}
-  `;
-};
-
-export { getAnimations, getStyles };
diff --git a/src/index.js b/src/index.js
index 27577f8..ca8d586 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,3 +1,2 @@
 export * from "./common/index.js";
 export * from "./cards/index.js";
-export { getStyles, getAnimations } from "./getStyles.js";


Test patch:
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 2050be0..69bd8ce 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -38,42 +38,8 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
       opacity: 0;
       animation: fadeInAnimation 0.3s ease-in-out forwards;
     }
-    .rank-text {
-      font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
-      animation: scaleInAnimation 0.3s ease-in-out forwards;
-    }
-    .rank-percentile-header {
-      font-size: 14px;
-    }
-    .rank-percentile-text {
-      font-size: 16px;
-    }
-    
     .not_bold { font-weight: 400 }
     .bold { font-weight: 700 }
-    .icon {
-      fill: #4c71f2;
-      display: none;
-    }
-
-    .rank-circle-rim {
-      stroke: undefined;
-      fill: none;
-      stroke-width: 6;
-      opacity: 0.2;
-    }
-    .rank-circle {
-      stroke: undefined;
-      stroke-dasharray: 250;
-      fill: none;
-      stroke-width: 6;
-      stroke-linecap: round;
-      opacity: 0.8;
-      transform-origin: -10px 8px;
-      transform: rotate(-90deg);
-      animation: rankAnimation 1s forwards ease-in-out;
-    }
-    
   
     @keyframes slideInAnimation {
       from {
@@ -224,42 +190,8 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
       opacity: 0;
       animation: fadeInAnimation 0.3s ease-in-out forwards;
     }
-    .rank-text {
-      font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58;
-      animation: scaleInAnimation 0.3s ease-in-out forwards;
-    }
-    .rank-percentile-header {
-      font-size: 14px;
-    }
-    .rank-percentile-text {
-      font-size: 16px;
-    }
-    
     .not_bold { font-weight: 400 }
     .bold { font-weight: 700 }
-    .icon {
-      fill: #4c71f2;
-      display: none;
-    }
-
-    .rank-circle-rim {
-      stroke: undefined;
-      fill: none;
-      stroke-width: 6;
-      opacity: 0.2;
-    }
-    .rank-circle {
-      stroke: undefined;
-      stroke-dasharray: 250;
-      fill: none;
-      stroke-width: 6;
-      stroke-linecap: round;
-      opacity: 0.8;
-      transform-origin: -10px 8px;
-      transform: rotate(-90deg);
-      animation: rankAnimation 1s forwards ease-in-out;
-    }
-    
   
     @keyframes slideInAnimation {
       from {