Repository: anuraghazra/github-readme-stats
Pull request #2519 (2023-02-14 13:12:06)

Fix wakatime progress bars - #2434
This PR fixes https://github.com/anuraghazra/github-readme-stats/issues/2434. The codebase could be cleaned up by moving the animation code into the `getStyles` function but I currently do not have the time to look at this. @Zo-Bro-23 feel free to improve this PR.

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

| Name | Status | Preview | Updated |
| :--- | :----- | :------ | :------ |
| **github-readme-stats** | ✅ Ready ([Inspect](https://vercel.com/github-readme-stats-team/github-readme-stats/6iMQVmfue2XSbgPdpE2Ebu2Lt3gn)) | [Visit Preview](https://github-readme-stats-git-fixwaka-605c1a-github-readme-stats-team.vercel.app) | Feb 14, 2023 at 1:12PM (UTC) |


codecov[bot]: # [Codecov](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2519?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) Report
Base: **97.25**% // Head: **97.27**% // Increases project coverage by **`+0.01%`** :tada:
> Coverage data is based on head [(`05d6b88`)](https://codecov.io/gh/anuraghazra/github-readme-stats/pull/2519?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) compared to base [(`888663a`)](https://codecov.io/gh/anuraghazra/github-readme-stats/commit/888663a47728a4e82a78dcc6fd95ce53bdaffc70?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    #2519      +/-   ##
==========================================
+ Coverage   97.25%   97.27%   +0.01%     
==========================================
  Files          24       24              
  Lines        4159     4183      +24     
  Branches      380      380              
==========================================
+ Hits         4045     4069      +24     
  Misses        112      112              
  Partials        2        2              
```


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

Zo-Bro-23: @rickstaa unfortunately I'm not very familiar with SVG or CSS. I can't really understand what the code does, so if you're convinced, then we will merge.

Patch:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index be97765..fad3eee 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,3 +1,4 @@
 themes: themes/index.js
 doc-translation: docs/*
 card-i18n: src/translations.js
+documentation: readme.md
diff --git a/.github/workflows/generate-theme-doc.yml b/.github/workflows/generate-theme-doc.yml
index d5fac06..75f6511 100644
--- a/.github/workflows/generate-theme-doc.yml
+++ b/.github/workflows/generate-theme-doc.yml
@@ -23,6 +23,10 @@ jobs:
           node-version: ${{ matrix.node-version }}
           cache: npm
 
+      # Fix the unsafe repo error which was introduced by the CVE-2022-24765 git patches.
+      - name: Fix unsafe repo error
+        run: git config --global --add safe.directory ${{ github.workspace }}
+
       - name: npm install, generate readme
         run: |
           npm ci
diff --git a/api/top-langs.js b/api/top-langs.js
index 19cccb8..e67d953 100644
--- a/api/top-langs.js
+++ b/api/top-langs.js
@@ -30,6 +30,7 @@ export default async (req, res) => {
     border_radius,
     border_color,
     disable_animations,
+    hide_progress,
   } = req.query;
   res.setHeader("Content-Type", "image/svg+xml");
 
@@ -77,6 +78,7 @@ export default async (req, res) => {
         border_color,
         locale: locale ? locale.toLowerCase() : null,
         disable_animations: parseBoolean(disable_animations),
+        hide_progress: parseBoolean(hide_progress),
       }),
     );
   } catch (err) {
diff --git a/readme.md b/readme.md
index 678c5c0..83f573e 100644
--- a/readme.md
+++ b/readme.md
@@ -133,7 +133,7 @@ You can add the count of all your private contributions to the total commits cou
 
 ### Showing icons
 
-To enable icons, you can pass `show_icons=true` in the query param, like so:
+To enable icons, you can pass `&show_icons=true` in the query param, like so:
 
 ```md
 ![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show_icons=true)
@@ -305,6 +305,7 @@ You can provide multiple comma-separated values in the bg_color option to render
 -   `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
 -   `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
 -   `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.
+-   `hide_progress` - It uses the compact layout option, hides percentages, and removes the bars. Default: `false`.
 
 > **Warning**
 > Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
@@ -398,6 +399,14 @@ You can use the `&layout=compact` option to change the card design.
 [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
 ```
 
+### Hide Progress Bars
+
+You can use the `&hide_progress=true` option to hide the percentages and the progress bars (layout will be automatically set to `compact`).
+
+```md
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+```
+
 ### Demo
 
 [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
@@ -406,6 +415,10 @@ You can use the `&layout=compact` option to change the card design.
 
 [![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
 
+- Hidden progress bars
+
+[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
+
 # Wakatime Week Stats
 
 Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js
index 9396ff8..be1328c 100644
--- a/src/cards/top-languages-card.js
+++ b/src/cards/top-languages-card.js
@@ -76,10 +76,11 @@ const createProgressTextNode = ({ width, color, name, progress, index }) => {
  * @param {object} props Function properties.
  * @param {Lang} props.lang Programming language object.
  * @param {number} props.totalSize Total size of all languages.
+ * @param {boolean} props.hideProgress Whether to hide percentage.
  * @param {number} props.index Index of the programming language.
  * @returns {string} Compact layout programming language SVG node.
  */
-const createCompactLangNode = ({ lang, totalSize, index }) => {
+const createCompactLangNode = ({ lang, totalSize, hideProgress, index }) => {
   const percentage = ((lang.size / totalSize) * 100).toFixed(2);
   const staggerDelay = (index + 3) * 150;
   const color = lang.color || "#858585";
@@ -88,7 +89,7 @@ const createCompactLangNode = ({ lang, totalSize, index }) => {
     <g class="stagger" style="animation-delay: ${staggerDelay}ms">
       <circle cx="5" cy="6" r="5" fill="${color}" />
       <text data-testid="lang-name" x="15" y="10" class='lang-name'>
-        ${lang.name} ${percentage}%
+        ${lang.name} ${hideProgress ? "" : percentage + "%"}
       </text>
     </g>
   `;
@@ -100,9 +101,10 @@ const createCompactLangNode = ({ lang, totalSize, index }) => {
  * @param {object[]} props Function properties.
  * @param {Lang[]} props.langs Array of programming languages.
  * @param {number} props.totalSize Total size of all languages.
+ * @param {boolean} props.hideProgress Whether to hide percentage.
  * @returns {string} Programming languages SVG node.
  */
-const createLanguageTextNode = ({ langs, totalSize }) => {
+const createLanguageTextNode = ({ langs, totalSize, hideProgress }) => {
   const longestLang = getLongestLang(langs);
   const chunked = chunkArray(langs, langs.length / 2);
   const layouts = chunked.map((array) => {
@@ -111,6 +113,7 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
       createCompactLangNode({
         lang,
         totalSize,
+        hideProgress,
         index,
       }),
     );
@@ -160,9 +163,10 @@ const renderNormalLayout = (langs, width, totalLanguageSize) => {
  * @param {Lang[]} langs Array of programming languages.
  * @param {number} width Card width.
  * @param {number} totalLanguageSize Total size of all languages.
+ * @param {boolean} hideProgress Whether to hide progress bar.
  * @returns {string} Compact layout card SVG object.
  */
-const renderCompactLayout = (langs, width, totalLanguageSize) => {
+const renderCompactLayout = (langs, width, totalLanguageSize, hideProgress) => {
   const paddingRight = 50;
   const offsetWidth = width - paddingRight;
   // progressOffset holds the previous language's width and used to offset the next language
@@ -193,15 +197,21 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {
     .join("");
 
   return `
-    <mask id="rect-mask">
+  ${
+    !hideProgress
+      ? `
+  <mask id="rect-mask">
       <rect x="0" y="0" width="${offsetWidth}" height="8" fill="white" rx="5"/>
     </mask>
     ${compactProgressBar}
-
-    <g transform="translate(0, 25)">
+  `
+      : ""
+  }
+    <g transform="translate(0, ${hideProgress ? "0" : "25"})">
       ${createLanguageTextNode({
         langs,
         totalSize: totalLanguageSize,
+        hideProgress: hideProgress,
       })}
     </g>
   `;
@@ -276,6 +286,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
     text_color,
     bg_color,
     hide,
+    hide_progress,
     theme,
     layout,
     custom_title,
@@ -305,11 +316,17 @@ const renderTopLanguages = (topLangs, options = {}) => {
   let height = calculateNormalLayoutHeight(langs.length);
 
   let finalLayout = "";
-  if (layout === "compact") {
+  if (layout === "compact" || hide_progress == true) {
     width = width + 50; // padding
-    height = calculateCompactLayoutHeight(langs.length);
-
-    finalLayout = renderCompactLayout(langs, width, totalLanguageSize);
+    height =
+      calculateCompactLayoutHeight(langs.length) + (hide_progress ? -25 : 0);
+
+    finalLayout = renderCompactLayout(
+      langs,
+      width,
+      totalLanguageSize,
+      hide_progress,
+    );
   } else {
     finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
   }
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index c5945d4..52ee0ed 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -38,6 +38,7 @@ export type TopLangOptions = CommonOptions & {
   custom_title: string;
   langs_count: number;
   disable_animations: boolean;
+  hide_progress: boolean;
 };
 
 type WakaTimeOptions = CommonOptions & {
diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js
index e7af1df..2c32955 100644
--- a/src/cards/wakatime-card.js
+++ b/src/cards/wakatime-card.js
@@ -118,6 +118,7 @@ const createTextNode = ({
         // @ts-ignore
         name: label,
         progressBarBackgroundColor,
+        delay: staggerDelay + 300,
       });
 
   return `
@@ -276,11 +277,12 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
   } else {
     finalLayout = flexLayout({
       items: filteredLanguages.length
-        ? filteredLanguages.map((language) => {
+        ? filteredLanguages.map((language, index) => {
             return createTextNode({
               id: language.name,
               label: language.name,
               value: language.text,
+              index: index,
               percent: language.percent,
               // @ts-ignore
               progressBarColor: titleColor,
@@ -321,7 +323,29 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
   card.setCSS(
     `
     ${cssStyles}
+    @keyframes slideInAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: calc(100%-100px);
+      }
+    }
+    @keyframes growWidthAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: 100%;
+      }
+    }
     .lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
+    #rect-mask rect{
+      animation: slideInAnimation 1s ease-in-out forwards;
+    }
+    .lang-progress{
+      animation: growWidthAnimation 0.6s ease-in-out forwards;
+    }
     `,
   );
 
diff --git a/themes/index.js b/themes/index.js
index 60825d1..01c9a8e 100644
--- a/themes/index.js
+++ b/themes/index.js
@@ -374,6 +374,13 @@ export const themes = {
     border_color: "170F0C",
     bg_color: "170F0C",
   },
+  one_dark_pro: {
+    title_color: "61AFEF",
+    text_color: "E5C06E",
+    icon_color: "C678DD",
+    border_color: "3B4048",
+    bg_color: "23272E",
+  },
   rose: {
     title_color: "8d192b",
     text_color: "862931",
@@ -381,6 +388,13 @@ export const themes = {
     border_color: "e9d8d4",
     bg_color: "e9d8d4",
   },
+  holi_theme: {
+    title_color: "5FABEE",
+    text_color: "D6E7FF",
+    icon_color: "5FABEE",
+    border_color: "85A4C0",
+    bg_color: "030314",
+  },
 };
 
 export default themes;


Test patch:
diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap
index 1c0bd70..6dfaf98 100644
--- a/tests/__snapshots__/renderWakatimeCard.test.js.snap
+++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap
@@ -69,7 +69,29 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
     }
     
   
+    @keyframes slideInAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: calc(100%-100px);
+      }
+    }
+    @keyframes growWidthAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: 100%;
+      }
+    }
     .lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58 }
+    #rect-mask rect{
+      animation: slideInAnimation 1s ease-in-out forwards;
+    }
+    .lang-progress{
+      animation: growWidthAnimation 0.6s ease-in-out forwards;
+    }
     
 
           
@@ -227,7 +249,29 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
     }
     
   
+    @keyframes slideInAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: calc(100%-100px);
+      }
+    }
+    @keyframes growWidthAnimation {
+      from {
+        width: 0;
+      }
+      to {
+        width: 100%;
+      }
+    }
     .lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: #434d58 }
+    #rect-mask rect{
+      animation: slideInAnimation 1s ease-in-out forwards;
+    }
+    .lang-progress{
+      animation: growWidthAnimation 0.6s ease-in-out forwards;
+    }