Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide specific languages in "Top languages" card #150

Merged
merged 7 commits into from
Jul 23, 2020
3 changes: 2 additions & 1 deletion api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ require("dotenv").config();
const {
renderError,
parseBoolean,
parseJSON,
clampValue,
CONSTANTS,
} = require("../src/utils");
Expand Down Expand Up @@ -44,7 +45,7 @@ module.exports = async (req, res) => {

res.send(
renderStatsCard(stats, {
hide: JSON.parse(hide || "[]"),
hide: parseJSON(hide),
show_icons: parseBoolean(show_icons),
hide_title: parseBoolean(hide_title),
hide_border: parseBoolean(hide_border),
Expand Down
5 changes: 3 additions & 2 deletions api/top-langs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const {
renderError,
clampValue,
parseBoolean,
parseJSON,
CONSTANTS,
} = require("../src/utils");
const fetchTopLanguages = require("../src/fetchTopLanguages");
Expand All @@ -11,7 +12,7 @@ const renderTopLanguages = require("../src/renderTopLanguages");
module.exports = async (req, res) => {
const {
username,
hide_langs_below,
hide,
hide_title,
card_width,
title_color,
Expand Down Expand Up @@ -43,7 +44,7 @@ module.exports = async (req, res) => {
theme,
hide_title: parseBoolean(hide_title),
card_width: parseInt(card_width, 10),
hide_langs_below: parseFloat(hide_langs_below, 10),
hide: parseJSON(hide),
title_color,
text_color,
bg_color,
Expand Down
36 changes: 18 additions & 18 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,21 @@ You can customize the appearance of your `Stats Card` or `Repo Card` however you

Customization Options:

| Option | type | description | Stats Card (default) | Repo Card (default) | Top Lang Card (default) |
| ---------------- | --------- | ---------------------------------------------- | -------------------- | ------------------- | ----------------------- |
| title_color | hex color | title color | 2f80ed | 2f80ed | 2f80ed |
| text_color | hex color | body color | 333 | 333 | 333 |
| icon_color | hex color | icon color | 4c71f2 | 586069 | 586069 |
| bg_color | hex color | card bg color | FFFEFE | FFFEFE | FFFEFE |
| line_height | number | control the line-height between text | 30 | N/A | N/A |
| hide_rank | boolean | hides the ranking | false | N/A | N/A |
| hide_title | boolean | hides the stats title | false | N/A | false |
| hide_border | boolean | hides the stats card border | false | N/A | N/A |
| show_owner | boolean | shows owner name in repo card | N/A | false | N/A |
| show_icons | boolean | shows icons | false | N/A | N/A |
| theme | string | sets inbuilt theme | 'default' | 'default_repocard' | 'default |
| cache_seconds | number | manually set custom cache control | 1800 | 1800 | '1800' |
| hide_langs_below | number | hide langs below certain threshold (lang card) | N/A | N/A | undefined |
| Option | type | description | Stats Card (default) | Repo Card (default) | Top Lang Card (default) |
| ------------- | ---------- | -------------------------------------- | -------------------- | ------------------- | ----------------------- |
| title_color | hex color | title color | 2f80ed | 2f80ed | 2f80ed |
| text_color | hex color | body color | 333 | 333 | 333 |
| icon_color | hex color | icon color | 4c71f2 | 586069 | 586069 |
| bg_color | hex color | card bg color | FFFEFE | FFFEFE | FFFEFE |
| line_height | number | control the line-height between text | 30 | N/A | N/A |
| hide | JSON array | hides the items specified on the array | [] | N/A | [] |
| hide_rank | boolean | hides the ranking | false | N/A | N/A |
| hide_title | boolean | hides the stats title | false | N/A | false |
| hide_border | boolean | hides the stats card border | false | N/A | N/A |
| show_owner | boolean | shows owner name in repo card | N/A | false | N/A |
| show_icons | boolean | shows icons | false | N/A | N/A |
| theme | string | sets inbuilt theme | 'default' | 'default_repocard' | 'default |
| cache_seconds | number | manually set custom cache control | 1800 | 1800 | '1800' |

> Note on cache: Repo cards have default cache of 30mins (1800 seconds) if the fork count & star count is less than 1k otherwise it's 2hours (7200). Also note that cache is clamped to minimum of 30min and maximum of 24hours

Expand Down Expand Up @@ -155,12 +155,12 @@ Endpoint: `api/top-langs?username=anuraghazra`
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)
```

### Hide languages below certain threshold
### Hide individual languages

You can use `?hide_langs_below=NUMBER` parameter to hide languages below a specified threshold percentage.
You can use `?hide=["language1","language2"]` parameter to hide languages below a specified threshold percentage.

```md
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide_langs_below=1)](https://github.com/anuraghazra/github-readme-stats)
[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&hide=["javascript","html"])](https://github.com/anuraghazra/github-readme-stats)
```

### Demo
Expand Down
24 changes: 17 additions & 7 deletions src/renderTopLanguages.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,41 @@ const createProgressNode = ({ width, color, name, progress }) => {
`;
};

const lowercaseTrim = (name) => name.toLowerCase().trim();

const renderTopLanguages = (topLangs, options = {}) => {
const {
hide_title,
card_width,
title_color,
text_color,
bg_color,
hide_langs_below,
hide,
theme,
} = options;

let langs = Object.values(topLangs);
let langsToHide = {};

const totalSize = langs.reduce((acc, curr) => {
return acc + curr.size;
}, 0);
// populate langsToHide map for quick lookup
// while filtering out
if (hide) {
hide.forEach((langName) => {
langsToHide[lowercaseTrim(langName)] = true;
});
}

// hide langs
// filter out langauges to be hidden
langs = langs
.sort((a, b) => b.size - a.size)
.filter((lang) => {
if (!hide_langs_below) return true;
return (lang.size / totalSize) * 100 > hide_langs_below;
return !langsToHide[lowercaseTrim(lang.name)];
});

const totalSize = langs.reduce((acc, curr) => {
return acc + curr.size;
}, 0);

// returns theme based colors with proper overrides and defaults
const { titleColor, textColor, bgColor } = getCardColors({
title_color,
Expand Down
12 changes: 11 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ function parseBoolean(value) {
}
}

function parseJSON(str) {
try {
return JSON.parse(str);
} catch (err) {
return [];
}
}

function clampValue(number, min, max) {
return Math.max(min, Math.min(number, max));
}
Expand Down Expand Up @@ -118,7 +126,8 @@ function getCardColors({

const fn = () => {};
// return console instance based on the environment
const logger = process.env.NODE_ENV !== "test" ? console : { log: fn, error: fn };
const logger =
process.env.NODE_ENV !== "test" ? console : { log: fn, error: fn };

const CONSTANTS = {
THIRTY_MINUTES: 1800,
Expand All @@ -132,6 +141,7 @@ module.exports = {
encodeHTML,
isValidHexColor,
request,
parseJSON,
parseBoolean,
fallbackColor,
FlexLayout,
Expand Down
18 changes: 13 additions & 5 deletions tests/renderTopLanguages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,26 @@ describe("Test renderTopLanguages", () => {
);
});

it("should hide_langs_below", () => {
it("should hide languages when hide is passed", () => {
document.body.innerHTML = renderTopLanguages(langs, {
hide_langs_below: 34,
hide: ["HTML"],
});

expect(queryAllByTestId(document.body, "lang-name")[0]).toBeInTheDocument(
"HTML"
"javascript"
);
expect(queryAllByTestId(document.body, "lang-name")[1]).toBeInTheDocument(
"javascript"
"css"
);
expect(queryAllByTestId(document.body, "lang-name")[2]).not.toBeDefined();

// multiple languages passed
document.body.innerHTML = renderTopLanguages(langs, {
hide: ["HTML","css"],
});
expect(queryAllByTestId(document.body, "lang-name")[0]).toBeInTheDocument(
"javascript"
);
expect(queryAllByTestId(document.body, "lang-name")[1]).not.toBeDefined();
});

it("should resize the height correctly depending on langs", () => {
Expand Down