Repository: anuraghazra/github-readme-stats
Pull request #3453 (2023-11-02 18:19:35)

feature(repo card): add description lines count query parameter
Before:

<div align="center"> 
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=rjyo&repo=Air-Test"/>
</a>
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=meako689&repo=FortyTwoTestTask"/>
</a>
</div>

After (`&description_lines_count=3`):

<div align="center"> 
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=rjyo&repo=Air-Test&description_lines_count=3"/>
</a>
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=meako689&repo=FortyTwoTestTask&description_lines_count=3"/>
</a>
</div>

After (`&description_lines_count=1`):

<div align="center"> 
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=rjyo&repo=Air-Test&description_lines_count=1"/>
</a>
<a href="https://github.com/anuraghazra/github-readme-stats">
<img src="https://github-readme-stats-52eik9zo5-github-readme-stats-team.vercel.app/api/pin/?username=meako689&repo=FortyTwoTestTask&description_lines_count=1"/>
</a>
</div>

vercel[bot]: [vc]: #+YtYkxT18QRTbzPUGRybjTtR23nhmAfPmNl8oGsTgyw=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJnaXRodWItcmVhZG1lLXN0YXRzIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2dpdGh1Yi1yZWFkbWUtc3RhdHMtdGVhbS9naXRodWItcmVhZG1lLXN0YXRzLzVpYmNieW45bTZNZFdkeXF3M3VXZjZQcU52TFkiLCJwcmV2aWV3VXJsIjoiZ2l0aHViLXJlYWRtZS1zdGF0cy1naXQtZmVhdHVyZS0xNWFiN2MtZ2l0aHViLXJlYWRtZS1zdGF0cy10ZWFtLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQifV19
**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** | ✅ Ready ([Inspect](https://vercel.com/github-readme-stats-team/github-readme-stats/5ibcbyn9m6MdWdyqw3uWf6PqNvLY)) | [Visit Preview](https://github-readme-stats-git-feature-15ab7c-github-readme-stats-team.vercel.app) | Nov 2, 2023 6:19pm |


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) Report
Attention: `4 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`5b3b920`)](https://app.codecov.io/gh/anuraghazra/github-readme-stats/commit/5b3b920ed277147b3236d978152df4796a95c128?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) 98.43% compared to head [(`067f9b4`)](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) 98.36%.

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


```diff
@@            Coverage Diff             @@
##           master    #3453      +/-   ##
==========================================
- Coverage   98.43%   98.36%   -0.07%     
==========================================
  Files          26       26              
  Lines        6117     6133      +16     
  Branches      535      536       +1     
==========================================
+ Hits         6021     6033      +12     
- Misses         93       97       +4     
  Partials        3        3              
```


| [Files](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra) | Coverage Δ | |
|---|---|---|
| [api/pin.js](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra#diff-YXBpL3Bpbi5qcw==) | `98.33% <100.00%> (+0.02%)` | :arrow_up: |
| [src/cards/repo-card.js](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Anurag+Hazra#diff-c3JjL2NhcmRzL3JlcG8tY2FyZC5qcw==) | `97.92% <75.00%> (-2.08%)` | :arrow_down: |


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/anuraghazra/github-readme-stats/pull/3453?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).

qwerty541: > Approved. I asked @anuraghazra for a last review, but if documentation and tests are added, I now think this feature is good to merge.

I added test in my recent commit, please check it. And this pull request already contains documentation.
qwerty541: Or do you mean adding examples using this feature?
rickstaa: > Or do you mean adding examples using this feature?

No, the pull request now looks good! I approved it so that it can be merged whenever you're ready 👍🏻.

Patch:
diff --git a/api/pin.js b/api/pin.js
index c67df29..0bc029d 100644
--- a/api/pin.js
+++ b/api/pin.js
@@ -24,6 +24,7 @@ export default async (req, res) => {
     locale,
     border_radius,
     border_color,
+    description_lines_count,
   } = req.query;
 
   res.setHeader("Content-Type", "image/svg+xml");
@@ -96,6 +97,7 @@ export default async (req, res) => {
         border_color,
         show_owner: parseBoolean(show_owner),
         locale: locale ? locale.toLowerCase() : null,
+        description_lines_count,
       }),
     );
   } catch (err) {
diff --git a/readme.md b/readme.md
index a176615..0f10671 100644
--- a/readme.md
+++ b/readme.md
@@ -386,6 +386,7 @@ If we don't support your language, please consider contributing! You can find mo
 #### Repo Card Exclusive Options
 
 *   `show_owner` - Shows the repo's owner name *(boolean)*. Default: `false`.
+*   `description_lines_count` - Manually set the number of lines for the description *(number)*. Specified value will be clamped between 1 and 3. If this parameter is not specified, the number of lines will be automatically adjusted according to the actual length of the description. Default: `undefined`.
 
 #### Gist Card Exclusive Options
 
diff --git a/src/cards/repo-card.js b/src/cards/repo-card.js
index 0d32475..bbfda52 100644
--- a/src/cards/repo-card.js
+++ b/src/cards/repo-card.js
@@ -12,10 +12,13 @@ import {
   wrapTextMultiline,
   iconWithLabel,
   createLanguageNode,
+  clampValue,
 } from "../common/utils.js";
 import { repoCardLocales } from "../translations.js";
 
 const ICON_SIZE = 16;
+const DESCRIPTION_LINE_WIDTH = 59;
+const DESCRIPTION_MAX_LINES = 3;
 
 /**
  * Retrieves the repository description and wraps it to fit the card width.
@@ -73,22 +76,34 @@ const renderRepoCard = (repo, options = {}) => {
     border_radius,
     border_color,
     locale,
+    description_lines_count,
   } = options;
 
   const lineHeight = 10;
   const header = show_owner ? nameWithOwner : name;
   const langName = (primaryLanguage && primaryLanguage.name) || "Unspecified";
   const langColor = (primaryLanguage && primaryLanguage.color) || "#333";
+  const descriptionMaxLines = description_lines_count
+    ? clampValue(description_lines_count, 1, DESCRIPTION_MAX_LINES)
+    : DESCRIPTION_MAX_LINES;
 
   const desc = parseEmojis(description || "No description provided");
-  const multiLineDescription = wrapTextMultiline(desc);
-  const descriptionLines = multiLineDescription.length;
+  const multiLineDescription = wrapTextMultiline(
+    desc,
+    DESCRIPTION_LINE_WIDTH,
+    descriptionMaxLines,
+  );
+  const descriptionLinesCount = description_lines_count
+    ? clampValue(description_lines_count, 1, DESCRIPTION_MAX_LINES)
+    : multiLineDescription.length;
+
   const descriptionSvg = multiLineDescription
     .map((line) => `<tspan dy="1.2em" x="25">${encodeHTML(line)}</tspan>`)
     .join("");
 
   const height =
-    (descriptionLines > 1 ? 120 : 110) + descriptionLines * lineHeight;
+    (descriptionLinesCount > 1 ? 120 : 110) +
+    descriptionLinesCount * lineHeight;
 
   const i18n = new I18n({
     locale,
diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts
index dce964d..d55d1c6 100644
--- a/src/cards/types.d.ts
+++ b/src/cards/types.d.ts
@@ -32,6 +32,7 @@ export type StatCardOptions = CommonOptions & {
 
 export type RepoCardOptions = CommonOptions & {
   show_owner: boolean;
+  description_lines_count: number;
 };
 
 export type TopLangOptions = CommonOptions & {


Test patch:
diff --git a/tests/renderRepoCard.test.js b/tests/renderRepoCard.test.js
index 050e710..abbad4d 100644
--- a/tests/renderRepoCard.test.js
+++ b/tests/renderRepoCard.test.js
@@ -339,4 +339,34 @@ describe("Test renderRepoCard", () => {
       "No description provided",
     );
   });
+
+  it("should have correct height with specified `description_lines_count` parameter", () => {
+    // Testing short description
+    document.body.innerHTML = renderRepoCard(data_repo.repository, {
+      description_lines_count: 1,
+    });
+    expect(document.querySelector("svg")).toHaveAttribute("height", "120");
+    document.body.innerHTML = renderRepoCard(data_repo.repository, {
+      description_lines_count: 3,
+    });
+    expect(document.querySelector("svg")).toHaveAttribute("height", "150");
+
+    // Testing long description
+    const longDescription =
+      "A tool that will make a lot of iPhone/iPad developers' life easier. It shares your app over-the-air in a WiFi network. Bonjour is used and no configuration is needed.";
+    document.body.innerHTML = renderRepoCard(
+      { ...data_repo.repository, description: longDescription },
+      {
+        description_lines_count: 3,
+      },
+    );
+    expect(document.querySelector("svg")).toHaveAttribute("height", "150");
+    document.body.innerHTML = renderRepoCard(
+      { ...data_repo.repository, description: longDescription },
+      {
+        description_lines_count: 1,
+      },
+    );
+    expect(document.querySelector("svg")).toHaveAttribute("height", "120");
+  });
 });